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

SingleThreadEventLoop 实现

public abstract class SingleThreadEventLoop extends SingleThreadEventExecutor implements EventLoop {
private final Queue<Runnable> tailTasks; @Override
protected void afterRunningAllTasks() {
runAllTasksFrom(tailTasks);
}
}

SingleThreadEventLoop是个抽象类,从实现代码上看出很简单的逻辑边界判断

SingleThreadEventExecutor也是个抽象类,代码量比较大,我们先看重要的成员属性

public abstract class SingleThreadEventExecutor extends AbstractScheduledEventExecutor implements OrderedEventExecutor {
//事件队列
private final Queue<Runnable> taskQueue;
//执行事件线程,可以看出只有一个线程只要用来记录executor的当前线程
private volatile Thread thread;
//主要负责监控该线程的生命周期,提取出当前线程然后用thread记录
private final Executor executor;
//用Atomic*技术记录当前线程状态
private static final AtomicIntegerFieldUpdater<SingleThreadEventExecutor> STATE_UPDATER =
AtomicIntegerFieldUpdater.newUpdater(SingleThreadEventExecutor.class, "state");
} //启动线程做了比较判断
private void startThread() {
if (STATE_UPDATER.get(this) == ST_NOT_STARTED) {
if (STATE_UPDATER.compareAndSet(this, ST_NOT_STARTED, ST_STARTED)) {
doStartThread();
}
}
} private void doStartThread() {
executor.execute(new Runnable() {
@Override
public void run() {
//记录当前执行线程
thread = Thread.currentThread();
if (interrupted) {
thread.interrupt();
} boolean success = false;
updateLastExecutionTime();
try {
//这里调用的是子类,注意子类是死循环不停的执行任务
SingleThreadEventExecutor.this.run();
success = true;
} catch (Throwable t) {
logger.warn("Unexpected exception from an event executor: ", t);
} finally {
//更改线程结束状态 省略部分代码
for (;;) {
int oldState = STATE_UPDATER.get(SingleThreadEventExecutor.this);
if (oldState >= ST_SHUTTING_DOWN || STATE_UPDATER.compareAndSet(
SingleThreadEventExecutor.this, oldState, ST_SHUTTING_DOWN)) {
break;
}
}
try {
// 执行未完成任务同 shutdown hooks.
for (;;) {
if (confirmShutdown()) {
break;
}
}
} finally {
try {
//最后清理操作,如 NioEventLoop实现 selector.close();
cleanup();
} finally {
//省略部分代码
}
}
}
}
});
}
protected final boolean runAllTasksFrom(Queue<Runnable> taskQueue) {
Runnable task = pollTaskFrom(taskQueue);
if (task == null) {
return false;
}
for (;;) {
//安全执行任务
safeExecute(task);
//继续执行剩余任务
task = pollTaskFrom(taskQueue);
if (task == null) {
return true;
}
}
} protected final Runnable pollTaskFrom(Queue<Runnable> taskQueue) {
for (;;) {
Runnable task = taskQueue.poll();
//忽略WAKEUP_TASK类型任务
if (task == WAKEUP_TASK) {
continue;
}
return task;
}
} protected boolean runAllTasks(long timeoutNanos) {
//先执行周期任务
fetchFromScheduledTaskQueue();
//从taskQueue提一个任务,如果为空执行所有tailTasks
Runnable task = pollTask();
//如果taskQueue没有任务,立即执行子类的tailTasks
if (task == null) {
afterRunningAllTasks();
return false;
}
//计算出超时时间 = 当前 nanoTime + timeoutNanos
final long deadline = ScheduledFutureTask.nanoTime() + timeoutNanos;
long runTasks = 0;
long lastExecutionTime;
for (;;) {
safeExecute(task); runTasks ++;
//当执行任务次数大于64判断是否超时,防止长时间独占CPU
if ((runTasks & 0x3F) == 0) {
lastExecutionTime = ScheduledFutureTask.nanoTime();
if (lastExecutionTime >= deadline) {
break;
}
} task = pollTask();
if (task == null) {
lastExecutionTime = ScheduledFutureTask.nanoTime();
break;
}
} afterRunningAllTasks();
this.lastExecutionTime = lastExecutionTime;
return true;
}
//SingleThreadEventLoop run 实现
public class DefaultEventLoop extends SingleThreadEventLoop { @Override
protected void run() {
for (;;) {
Runnable task = takeTask();
if (task != null) {
task.run();
updateLastExecutionTime();
} if (confirmShutdown()) {
break;
}
}
}
}

我们可以在SingleThreadEventExecutor  两个runAllTasks 方法打上断点,看执行任务时调用逻辑

本人为了搞清楚 taskQueue 同tailTasks 类型任务,在任务入队时打断点,分别为 SingleThreadEventLoop executeAfterEventLoopIteration方法同 SingleThreadEventExecutor offerTask方法

ServerBootstrap[bind address] ->

NioEventLoopGroup [register Channel] ->  [ChannelPromise] ->

NioEventLoop [build and push register task]

从调用链可以清晰看出,启动 netty server 绑定生成抽象 Channel 然后l转换成ChannelPromise,再调用注册实现register0

这里用了判断是否为当前线程,如果是不用加入队列马上执行,目前减少上下文切换开削

if (eventLoop.inEventLoop()) {
register0(promise);
} else {
eventLoop.execute(new Runnable() {
@Override
public void run() {
register0(promise);
}
});
}

总结:

1.SingleThreadEventLoop 任务执行加了超时限制,目的防止当前线程长时间执行任务独占cpu

2.提交任务时做了减少上下文开削优化

3.执行任务优先级 1.周期任务 2.taskQueue 3.tailTasks

目前没有看到任何调用 SingleThreadEventLoop executeAfterEventLoopIteration 方法,估计是扩展处理。

4.用到Atomic*技术解决并发问题,从Executor提取当前线程,把单一线程维护交给Executor

[编织消息框架][netty源码分析]3 EventLoop 实现类SingleThreadEventLoop职责与实现的更多相关文章

  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源码分析]6 ChannelPipeline 实现类DefaultChannelPipeline职责与实现

    ChannelPipeline 负责channel数据进出处理,如数据编解码等.采用拦截思想设计,经过A handler处理后接着交给next handler ChannelPipeline 并不是直 ...

  4. [编织消息框架][netty源码分析]11 ByteBuf 实现类UnpooledHeapByteBuf职责与实现

    每种ByteBuf都有相应的分配器ByteBufAllocator,类似工厂模式.我们先学习UnpooledHeapByteBuf与其对应的分配器UnpooledByteBufAllocator 如何 ...

  5. [编织消息框架][netty源码分析]8 Channel 实现类NioSocketChannel职责与实现

    Unsafe是托委访问socket,那么Channel是直接提供给开发者使用的 Channel 主要有两个实现 NioServerSocketChannel同NioSocketChannel 致于其它 ...

  6. [编织消息框架][netty源码分析]9 Promise 实现类DefaultPromise职责与实现

    netty Future是基于jdk Future扩展,以监听完成任务触发执行Promise是对Future修改任务数据DefaultPromise是重要的模板类,其它不同类型实现基本是一层简单的包装 ...

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

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

  8. [编织消息框架][netty源码分析]7 Unsafe 实现类NioSocketChannelUnsafe职责与实现

    Unsafe 是channel的内部接口,从书写跟命名上看是不公开给开发者使用的,直到最后实现NioSocketChannelUnsafe也没有公开出去 public interface Channe ...

  9. [编织消息框架][netty源码分析]13 ByteBuf 实现类CompositeByteBuf职责与实现

    public class CompositeByteBuf extends AbstractReferenceCountedByteBuf implements Iterable<ByteBuf ...

随机推荐

  1. windows安装cygwin实现gcc/g++/linux操作等功能

    首先安装cygwin:参照下列博客去cygwin官网下载即可.安装过程中记得勾选需要的安装包,比如gcc/gdb https://blog.csdn.net/qilvmilv/article/deta ...

  2. LUOGU P1084 疫情控制(二分+贪心+树上倍增)

    传送门 解题思路 比较神的一道题.首先发现是最小值问题,并且具有单调性,所以要考虑二分答案.其次有一个性质是军队越靠上越优,所以我们要将所有的军队尽量向上提,这一过程我们用倍增实现.发现这时有两种军队 ...

  3. Unable to find explicit activity class报错问题解决方法

    转:http://hi.baidu.com/mz_mz/item/f5672ad814e1ce30e2108f69 1.首先查看是否在已经在AndroidMainfest.xml中添加了你的Activ ...

  4. 尚学python课程---14、python中级语法

    尚学python课程---14.python中级语法 一.总结 一句话总结: var[1:5] 访问模式:比如字符串,比如列表元祖,字典等 del 删除模式:比如列表.元祖.字典 1.Python的N ...

  5. RPC 编程

    我们从一个简单的 RPC "Hello, world!"的例子开始. 参考资料:MSDN: Win32 and COM Development -> Networking - ...

  6. DELPHI指针的使用

    DELPHI指针的使用 大家都认为,C语言之所以强大,以及其自由性,很大部分体现在其灵活的指针运用上.因此,说指针是C语言的灵魂,一点都不为过.同时,这种说法也让很多人产生误解,似乎只有C语言的指针才 ...

  7. PHP面向对象魔术方法之__clone函数

    l 基本介绍 : 当我们需要将一个对象完全的赋值一份, 保证两个对象的属性和属性值一样,但是他们的数据库空间独立,则可以使用对象克隆. <?php header('content-type:te ...

  8. Spring Boot 发布 jar 包转为 war 包秘籍。

    Spring Boot是支持发布jar包和war的,但它推荐的是使用jar形式发布.使用jar包比较方便,但如果是频繁修改更新的项目,需要打补丁包,那这么大的jar包上传都是问题.所以,jar包不一定 ...

  9. java-day09

    接口 就是一种公共规范标准,只要符合规范标准,就可以大家通用,多个类的公告规范,引用数据类型 格式 public interface 接口名称{} 接口都能定义抽象方法 public abstract ...

  10. 收藏的链接-Qt

    Qt编写的开源帖子集合(懒人专用) - QTCN开发网 - Powered by phpwind http://www.qtcn.org/bbs/read-htm-tid-85501.html?tds ...