上一篇主要介绍了一下EventLoopGroup,本篇详细看下它的成员EventLoop

类结构



NioEventLoop继承自SingleThreadEventLoop,而SingleThreadEventLoop又继承自SingleThreadEventExecutor

SingleThreadEventExecutor内部持有一个Thread对象,是Netty多线程的基础。

可以认为, 一个NioEventLoop与一个特定的线程进行了绑定,并且在其生命周期内,绑定的线程都不会再改变。

SingleThreadEventExecutor

从名字就可以看出来,SingleThreadEventExecutor是一个单线程事件执行器。主要做的事情就是线程的管理和事件的执行。

线程管理

SingleThreadEventExecutor中定义了五种线程状态:

    /**
* 未开始
*/
private static final int ST_NOT_STARTED = 1;
/**
* 已开始
*/
private static final int ST_STARTED = 2;
/**
* 关闭中
*/
private static final int ST_SHUTTING_DOWN = 3;
/**
* 已关闭
*/
private static final int ST_SHUTDOWN = 4;
/**
* 已终止
*/
private static final int ST_TERMINATED = 5;

这几种状态对应的方法有startThreadshutdownGracefullyshutdown

startThread

    private void startThread() {
if (state == ST_NOT_STARTED) {
if (STATE_UPDATER.compareAndSet(this, ST_NOT_STARTED, ST_STARTED)) {
try {
doStartThread();
} catch (Throwable cause) {
STATE_UPDATER.set(this, ST_NOT_STARTED);
PlatformDependent.throwException(cause);
}
}
}
}

startThread线程未开始时,尝试更新线程状态为一开始,更新成功,则调用doStartThread方法启动线程,子类的run方法就是在这里调用的,比如说接下来的NioEventLoop

shutdownGracefully

    public Future<?> shutdownGracefully(long quietPeriod, long timeout, TimeUnit unit) {
// 静待时间需要>=0
if (quietPeriod < 0) {
throw new IllegalArgumentException("quietPeriod: " + quietPeriod + " (expected >= 0)");
}
// 超时时间不能小于静待时间
if (timeout < quietPeriod) {
throw new IllegalArgumentException(
"timeout: " + timeout + " (expected >= quietPeriod (" + quietPeriod + "))");
}
// 必须设置时间单位
if (unit == null) {
throw new NullPointerException("unit");
}
// 关闭中直接返回终止Future
if (isShuttingDown()) {
return terminationFuture();
}
boolean inEventLoop = inEventLoop();
boolean wakeup;
int oldState;
for (; ; ) {
// 关闭中直接返回终止Future
if (isShuttingDown()) {
return terminationFuture();
}
int newState;
wakeup = true;
oldState = state;
if (inEventLoop) {
newState = ST_SHUTTING_DOWN;
} else {
switch (oldState) {
case ST_NOT_STARTED:
case ST_STARTED:
newState = ST_SHUTTING_DOWN;
break;
default:
newState = oldState;
wakeup = false;
}
}
if (STATE_UPDATER.compareAndSet(this, oldState, newState)) {
break;
}
}
gracefulShutdownQuietPeriod = unit.toNanos(quietPeriod);
gracefulShutdownTimeout = unit.toNanos(timeout);
if (oldState == ST_NOT_STARTED) {
try {
doStartThread();
} catch (Throwable cause) {
STATE_UPDATER.set(this, ST_TERMINATED);
terminationFuture.tryFailure(cause); if (!(cause instanceof Exception)) {
PlatformDependent.throwException(cause);
}
return terminationFuture;
}
}
if (wakeup) {
wakeup(inEventLoop);
} return terminationFuture();
}

shutdownGracefully目的是让正在执行的任务再执行一会儿,同时拒绝新任务。quietPeriodtimeout这两个时间会在confirmShutdown方法中用到,当然单位已经转为纳秒了。

事件的执行

   public void execute(Runnable task) {
if (task == null) {
throw new NullPointerException("task");
}
boolean inEventLoop = inEventLoop();
if (inEventLoop) {
addTask(task);
} else {
startThread();
addTask(task);
if (isShutdown() && removeTask(task)) {
reject();
}
}
if (!addTaskWakesUp && wakesUpForTask(task)) {
wakeup(inEventLoop);
}
}

NioEventLoop

NioEventLoop的核心操作都在它的run方法里面:

    protected void run() {
for (; ; ) {
try {
switch (selectStrategy.calculateStrategy(selectNowSupplier, hasTasks())) {
case SelectStrategy.CONTINUE:
continue;
case SelectStrategy.SELECT:
// 重置wakenUp为false并选择任务
select(wakenUp.getAndSet(false));
if (wakenUp.get()) {
selector.wakeup();
}
default:
}
cancelledKeys = 0;
needsToSelectAgain = false;
final int ioRatio = this.ioRatio;
// 当处理io用时占比为100%时
if (ioRatio == 100) {
try {
processSelectedKeys();
} finally {
runAllTasks();
}
} else {
final long ioStartTime = System.nanoTime();
try {
processSelectedKeys();
} finally {
final long ioTime = System.nanoTime() - ioStartTime;
runAllTasks(ioTime * (100 - ioRatio) / ioRatio);
}
}
} catch (Throwable t) {
// 处理Loop异常
handleLoopException(t);
}
try {
// 处于关闭状态
if (isShuttingDown()) {
// 关闭所有
closeAll();
if (confirmShutdown()) {
return;
}
}
} catch (Throwable t) {
// 处理Loop异常
handleLoopException(t);
}
}
}

该方法主要是处理流程的控制,包括选择、处理和关闭这几种。

文中帖的代码注释全在:KAMIJYOUDOUMA, 有兴趣的童鞋可以关注一下。


本篇到此结束,如果读完觉得有收获的话,欢迎点赞、关注、加公众号【贰级天災】,查阅更多精彩历史!!!

Netty源码分析(五):EventLoop的更多相关文章

  1. [编织消息框架][netty源码分析]4 eventLoop 实现类NioEventLoop职责与实现

    NioEventLoop 是jdk nio多路处理实现同修复jdk nio的bug 1.NioEventLoop继承SingleThreadEventLoop 重用单线程处理 2.NioEventLo ...

  2. [编织消息框架][netty源码分析]5 eventLoop 实现类NioEventLoopGroup职责与实现

    分析NioEventLoopGroup最主有两个疑问 1.next work如何分配NioEventLoop 2.boss group 与child group 是如何协作运行的 从EventLoop ...

  3. [编织消息框架][netty源码分析]2 eventLoop

    eventLoop从命名上看是专门处理事件 事件系统主要由线程池同队列技术组成,有以下几个优点 1.任务出队有序执行,不会出现错乱,当然前提执行线程池只有一个 2.解偶系统复杂度,这是个经典的生产者/ ...

  4. [netty源码分析]3 eventLoop 实现类SingleThreadEventLoop职责与实现

    eventLoop是基于事件系统机制,主要技术由线程池同队列组成,是由生产/消费者模型设计,那么先搞清楚谁是生产者,消费者内容 SingleThreadEventLoop 实现 public abst ...

  5. [编织消息框架][netty源码分析]3 EventLoop 实现类SingleThreadEventLoop职责与实现

    eventLoop是基于事件系统机制,主要技术由线程池同队列组成,是由生产/消费者模型设计,那么先搞清楚谁是生产者,消费者内容 SingleThreadEventLoop 实现 public abst ...

  6. Netty源码分析第1章(Netty启动流程)---->第5节: 绑定端口

    Netty源码分析第一章:Netty启动步骤 第五节:绑定端口 上一小节我们学习了channel注册在selector的步骤, 仅仅做了注册但并没有监听事件, 事件是如何监听的呢? 我们继续跟第一小节 ...

  7. Netty源码分析第3章(客户端接入流程)---->第5节: 监听读事件

    Netty源码分析第三章: 客户端接入流程 第五节: 监听读事件 我们回到AbstractUnsafe的register0()方法: private void register0(ChannelPro ...

  8. Netty源码分析第4章(pipeline)---->第5节: 传播outbound事件

    Netty源码分析第五章: pipeline 第五节: 传播outBound事件 了解了inbound事件的传播过程, 对于学习outbound事件传输的流程, 也不会太困难 在我们业务代码中, 有可 ...

  9. Netty源码分析第7章(编码器和写数据)---->第5节: Future和Promies

    Netty源码分析第七章: 编码器和写数据 第五节: Future和Promise Netty中的Future, 其实类似于jdk的Future, 用于异步获取执行结果 Promise则相当于一个被观 ...

  10. 【Netty源码分析】客户端connect服务端过程

    上一篇博客[Netty源码分析]Netty服务端bind端口过程 我们介绍了服务端绑定端口的过程,这一篇博客我们介绍一下客户端连接服务端的过程. ChannelFuture future = boos ...

随机推荐

  1. ORA-01017 invalid username/password;logon denied

    一般来说这个是密码丢失问题,但也许是因为你的用户名或密码写错啦,所以先检查下用户名和密码,觉得没错的话就去查看 sqlnet.ora (在 安装盘下面的:oracle\product\11.2.0\d ...

  2. php发送http put/patch/delete请求Demo

    CURL请求对于PHPer是必备技能,使用curl_opt函数来发送各式各样的http请求动作,不仅限于get和post.在测试自己的restful api的时候,通过访问这个代理发送http put ...

  3. (转)MySql中监视增删改查和查看日志记录

    转载地址为:http://blog.51cto.com/hades02/1641652 首先在命令行输入 show global variables like '%general%' ,然后出现下面的 ...

  4. jenkins maven git windows code 自动部署

    本人刚刚接触  写的不好就对付看看吧 哈哈哈O(∩_∩)O哈哈~ 最近看见别人弄得自动部署 自己也是手痒痒 也想弄一个 所以就弄了一个 windows的 我用的是https的  在网上看了很多都是 s ...

  5. (26)A delightful way to teach kids about computers

    https://www.ted.com/talks/linda_liukas_a_delightful_way_to_teach_kids_about_computers/transcript00:1 ...

  6. 解决:Adobe Acrobat Pro中设置背景颜色后,出现白色条纹

    找到  编辑->首选项->页面显示->渲染->使用2D图形加速 取消即可

  7. s6-8 TCP 拥塞控制

    TCP 拥塞控制  虽然网络层也试图管理拥塞,但是,大多数繁重的任务是由TCP来完成的,因为针对拥塞的真正解决方案是减慢数据率  分组守恒:当有一个老的分组离开之后才允许新的分组注入网络  TC ...

  8. c语言构建哈希表

    /*哈希查找 *哈希函数的构造方法常用的有5种.分别是: *数字分析法 *平方取中法 *分段叠加 *伪随机数 *除留取余法 *这里面除留取余法比较常用 *避免哈希冲突常用的方法有4种: *开放定址法( ...

  9. Kalman Filters

    |—定位—|—蒙特卡洛方法(定位自身) |              |—卡尔曼滤波器(定位其他车辆) |—高斯函数 |—循环两个过程—|—测量(测量更新) |                     ...

  10. html-有趣的标签-会移动的文字

    <!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8" ...