前面花了5节的篇幅来学习和研究NioEventLoop的创建,启动,执行的过程。总结一下
- 用户代码再创建
boosGroup
和workGroup
的时候,NioEventLoop
被创建,默认不穿参数的时候,创建2倍CPU核心数
的NioEventLoop
- 每一个
NioEventLoop
都会又一个chooser
进行线程逻辑的分配,该chooser
也会针对NioEventLoop
的个数进行一些优化。 - 创建
NioEventLoop
的时候会创建一个selector
和一个定时任务队列scheduledTaskQueue
,并且创建selector
的时候,创建了一个数组实现的SelectedSelectionKeySet
替换掉原有HashSet实现的两个属性 selectedKeys和publicSelectedKeys
-
NioEventLoop
再首次调用execute()
方法的时候启动FastThreadLocalThread
线程,并保存到成员变量,这样就可以判断执行NioEventLoop
执行逻辑的线程是否是当前线程。 -
NioEventLoop
的执行逻辑再run()
方法,包括三个过程,分别是:
(1)检测IO事件
(2)处理这些IO事件
(3)执行任务队列
几个问题:
- 默认情况下,Netty服务端开启多少个线程?何时启动
开启2倍的CPU核心数的线程,在调用
execute()
的时候,会判断当前线程是否是NioEventLoop
持有的线程,如果是的话,表示已经启动;不是的话,表面外部线程调用本eventLoop
,嗲用startThread()
方法,判断当前线程是否有启动,没有则启动这个线程。
- netty是如何解决jdk空论的bug的
netty通过计数的方式,如果阻塞了一个select操作,实际上并没有花这么长时间,那么有可能出发了一次空轮询的bug,默认情况下,这个现象达到512次,则重建一个
Selector
,把原Selector
上面所有的key
移交到新的。通过这种方式避免。
- netty如何保证异步串行无锁化?
在所有外部线程调用
NioEventLoop
活Channle
的方法的时候,通过inEventLoop
方法来判断当前线程是本NioEventLoop
持有的线程(是否是外部线程),外部线程的话,则把所有操作封装成一个task
,丢到taskQueue
里面。而这个队列里的task
将会在NioEventLoop
执行的第三个阶段runAllTask()
中挨个执行,保证串行无锁化。
网友评论