2019-05-18 NioEventLoop的初始化
通过以下这行代码创建SubReactor线程组,也就是NioEventLoop线程组;


构造一个SelectorProvider.provider()
,这个provider就负责创建每个NioEventLoop维护的selector,同时初始化一个默认选择器执行策略

传入一个默认的线程选择器

创建一个默认的ThreadPerTaskExecutor,每次执行任务的时候都会创建一个线程,初始化是通过DefaultThreadFactory来创建的;

每次调用execute方法都会创建一个线程

构造DefaultThreadFactory,初始化线程的名称前缀


初始化NioEventLoop线程的名称前缀

创建线程的时候会将这个线程名传入对应的构造函数

netty中对jdk的Thread做了一层封装


创建NioEventLoop

代码在io.netty.channel.nio.NioEventLoopGroup#newChild这里实现,args参数如下


构造函数中设置executor,线程拒绝策略,taskQueue等

taskQueue:外部线程在执行netty的任务的时候,如果判断不是在NioEventLoop对应的线程里面去执行,这些任务会直接丢到一个任务队列中,然后由NioEventloop对应的线程去执行过程,初始化调用jdk底层初始化一个mscpQueue

mpscQueue(multi producer single consumer),multi producer对应的就是非Nio线程,Single consumer 就是netty的一个NioEventLoop线程,也就是说外部线程可以丢进来,由一个NioEventLoop去消费

最后就是绑定selector操作,注意看,其实每一个NioEventLoop都有一个对应的selector

最后创建EventExecutorChooser,chooser其实就是给新链接绑定NioEventLoop

NioEventLoop启动,通过dobind0方法新起一个Runnable进行端口绑定

什么时候channel绑定的NioEventLoop嘞?在这个地方实现的netty通过java.nio.channels.SelectableChannel#register(java.nio.channels.Selector, int, java.lang.Object)
方法将自身实现的NioSocketChannel和SelectionKey,原生的socket channel绑定在了一起

接下来看下execute方法,代码实现在io.netty.util.concurrent.SingleThreadEventExecutor#execute
,这里inEventLoop
返回false,所以就会启动一个新线程,并往TaskQueue添加任务

判断是不是NioEventLoop,这时候SingleThreadEventExecuto中的Thread的null,肯定不是当前主线程

启动线程,通过CAS判断当前线程是不是未启动的

接下来调用executor新建一个线程


首先保存当前线程,其实也就是将NioEventLoop与这个thread进行绑定

然后调用run方法进行实际的启动,其实这才是NioEventLoop的真实启动。

接下来就进入了NioEventLoop的run方法的执行了,这个我们后面再分析。