在前面我们已经知道了,NioEventLoop 本身就是一个SingleThreadEventExecutor,因此NioEventLoop 的启动,其实就是NioEventLoop 所绑定的本地Java 线程的启动。

按照这个思路,我们只需要找到在哪里调用了SingleThreadEventExecutor 中thread 字段的start()方法就可以知道是在哪里启动的这个线程了。从前面章节的分析中, 其实我们已经清楚: thread.start() 被封装到了SingleThreadEventExecutor.startThread()方法中,来看代码:

private void startThread() {if (STATE_UPDATER.get(this) == ST_NOT_STARTED) {if (STATE_UPDATER.compareAndSet(this, ST_NOT_STARTED, ST_STARTED)) {doStartThread();}}
}

STATE_UPDATER 是SingleThreadEventExecutor 内部维护的一个属性,它的作用是标识当前的thread 的状态。在初始的时候,STATE_UPDATER == ST_NOT_STARTED,因此第一次调用startThread()方法时,就会进入到if 语句内,进而调用到thread.start()方法。而这个关键的startThread()方法又是在哪里调用的呢?用方法调用关系反向查找功能,我们发现,startThread 是在SingleThreadEventExecutor 的execute()方法中调用的:

public void execute(Runnable task) {if (task == null) {throw new NullPointerException("task");}boolean inEventLoop = inEventLoop();if (inEventLoop) {addTask(task);} else {startThread(); // 调用startThread 方法、启动EventLoop 线程addTask(task);if (isShutdown() && removeTask(task)) {reject();}}if (!addTaskWakesUp && wakesUpForTask(task)) {wakeup(inEventLoop);}
}

既然如此,那现在我们的工作就变为了寻找在哪里第一次调用了SingleThreadEventExecutor 的execute()方法。

如果细心的小伙伴可能已想到了, 我们在前面章节中, 我们有提到到在注册channel 的过程中, 会在AbstractChannel$AbstractUnsafe 的register()中调用eventLoop.execute()方法,在EventLoop 中进行Channel 注册代码的执行,AbstractChannel$AbstractUnsafe 的register()部分代码如下:

public final void register(EventLoop eventLoop, final ChannelPromise promise) {// 删除判断AbstractChannel.this.eventLoop = eventLoop;if (eventLoop.inEventLoop()) {register0(promise);} else {try {eventLoop.execute(new Runnable() {@Overridepublic void run() {register0(promise);}});} catch (Throwable t) {// 删除异常处理代码}}
}

很显然,一路从Bootstrap 的bind()方法跟踪到AbstractChannel$AbstractUnsafe 的register()方法,整个代码都是在主线程中运行的,因此上面的eventLoop.inEventLoop()返回为false,于是进入到else 分支,在这个分支中调用了eventLoop.execute()方法,而NioEventLoop 没有实现execute()方法,因此调用的是SingleThreadEventExecutor 的execute()方法:

public void execute(Runnable task) {// 条件判断boolean inEventLoop = inEventLoop();if (inEventLoop) {addTask(task);} else {startThread();addTask(task);if (isShutdown() && removeTask(task)) {reject();}}if (!addTaskWakesUp && wakesUpForTask(task)) {wakeup(inEventLoop);}
}

我们已经分析过了, inEventLoop == false , 因此执行到else 分支, 在这里就调用startThread() 方法来启动SingleThreadEventExecutor 内部关联的Java 本地线程了。

总结一句话:当EventLoop 的execute()第一次被调用时,就会触发startThread()方法的调用,进而导致EventLoop所对应的Java 本地线程启动。

EventLoop 的启动相关推荐

  1. NioEventLoop启动流程源码解析

    NioEventLoop的启动时机是在服务端的NioServerSocketChannel中的ServerSocketChannel初始化完成,且注册在NioEventLoop后执行的, 下一步就是去 ...

  2. Android之rild进程启动源码分析

    Android 电话系统框架介绍 在android系统中rild运行在AP上,AP上的应用通过rild发送AT指令给BP,BP接收到信息后又通过rild传送给AP.AP与BP之间有两种通信方式: 1. ...

  3. Netty服务器启动源码剖析

    Netty服务器启动源码剖析 文章目录 Netty服务器启动源码剖析 1.Netty服务器启动源码剖析 1.1.执行new NioEventLoopGroup()时发生了什么 1.1.1.NioEve ...

  4. muduo之EventLoopThread

    muduo用EventLoopThread提供了对应eventloop和thread的封装,意为I/O线程类,EventLoopThread可以创建一个IO线程,通过startLoop返回一个IO线程 ...

  5. Netty新连接接入与NioSocketChannel分析

    原文链接:https://wangwei.one/posts/net... 前面的一些章节,我们分析了Netty的三大组件 -- Channel .EventLoop.Pipeline ,对Netty ...

  6. netty源码分析系列——Channel

    2019独角兽企业重金招聘Python工程师标准>>> 前言 Channel是netty中作为核心的一个概念,我们从启动器(Bootstrap)中了解到最终启动器的两个关键操作con ...

  7. Spark源码分析之DAGScheduler以及stage的划分

    一 核心属性 TaskScheduler taskScheduler: task调度器 AtomicInteger nextJobId: 获取下一个jobId Int numTotalJobs:job ...

  8. 30muduo_net库源码分析(六)

    1.EventThread (1)任何一个线程,只要创建并运行了EventLoop,都称之为IO线程 (2)IO线程不一定是主线程 (3)muduo并发模型one loop per thread + ...

  9. SparkSteaming运行流程分析以及CheckPoint操作

    本文主要通过源码来了解SparkStreaming程序从任务生成到任务完成整个执行流程以及中间伴随的checkpoint操作 注:下面源码只贴出跟分析内容有关的代码,其他省略 1 分析流程 应用程序入 ...

最新文章

  1. Kubernetes 1.8.4 手动安装教程-安装Dashboard(七)
  2. HDU2121(最小树形图的模版算法题)
  3. BadTunnel:跨网段劫持广播协议
  4. Sierpinski镂垫
  5. 牛客网_PAT乙级_1010月饼 (25)
  6. xunsearch安装使用
  7. 一个java文件中可包含多个main方法
  8. 云漫圈 | 什么是微服务?
  9. 主成分分析PCA案例及原理
  10. 架构设计(6)---Web架构师究竟都要学些什么?
  11. 2018腾讯内部转岗面试题2——打印A-Z 26个字母的所有子集
  12. For ourselves
  13. dell服务器错误代码
  14. 古希腊神话,古罗马神话和北欧神话
  15. 华硕电脑(博主电脑型号为天选FA506IH)Fn组合键屏幕不显示对应操作的解决办法!!
  16. 大数据之路,阿里巴巴大数据实践
  17. 电视制式 NTSC PAL SECAM
  18. 树莓派打造智能语音控制系统
  19. 烟花绽放c语言程序设计摘要,描写烟花绽放的优美句子
  20. CQHTTP 以HTTP形式制作你的QQ机器人

热门文章

  1. 使用logrotate切割nginx日志文件,其他日志文件切割类似
  2. Vb Shell 打开程序 等待运行完毕后再继续
  3. Java消息中间件的概述与JMS规范
  4. django 数据库中中文转化为汉语拼音
  5. javasript中var、let和const区别
  6. 创建应用服务器连接客户端
  7. socket的NIO操作
  8. 在实际开发中碰到的小问题,保存数据时提示:对象必须实现 IConvertible
  9. 全面详细的jQuery常见开发技巧手册
  10. 【抓包工具】Fiddler(详细介绍)