그물코 소스 코드 분석 --channel 등록 (ON) (V)

        사실, 이전에이 절에, 우리는 일이, 쉽게 좋은 일 다음 수행 할 분석 할 수 있습니다.

        시작 클래스를 열고, 맨 처음이 NioEventLoopGroup 이벤트 루프 그룹을 만들고, 이것에 대해 우리와 함께.

        

      여기 bossGroup, 나는 스레드에 도입, workerGroup없는 부모 나, 여러 스레드는 클라이언트가 읽기 및 쓰기 작업을 처리하기 위해 클라이언트 액세스를 처리하기 위해 스레드를 사용하는 것을 의미 상원, 기본 0으로

      공법의 일련을 체결

     집행자가 null, 인 SelectorProvider 멀티플렉서를 만들기 위해, 멀티플렉서의 정책에 마지막 인수, 우리는이 전략을 다시 올거야

    

     그런 다음 거부 전략에 확산으로 인해 NioEventLoopGroup는 MultithreadEventLoopGroup 상속, 그래서 MultithreadEventLoopGroup 생성자를 입력

     

    여기서의 판정은,이 bossGroup nThreads = 1에 있도록 1 도입; workerGroup하지 파라미터를 디폴트 스레드의 기본 수를 배치 할 위치가 결정되고, 0이다.

   

     이것은, NettyRuntime.availableProcessors () * 2 * 2 값 (하이퍼 스레드 프로세서의 수) CPU 코어의 수를 나타내고있다 * 2 * 2 값 또는 CPU의 개수  

     cmd를 명령 "WMIC"를 입력 한 다음 나타나는 새 창에서 "CPU가 * 얻을"를 입력합니다.
     NumberOfCores : CPU의 코어의 수를 나타냅니다
     NumberOfLogicalProcessors를 : CPU 스레드의 수를 나타냅니다

     

     所以我这里是 CPU核心数 是 2 , CPU 线程数 是 4 , 所以我的 NettyRuntime.availableProcessors() * 2 = 8, 然后这里Math.max(1,8) 取大的 就是 8 了

     所以我的 workerGroup 线程数 是 8

     好了,我们继续跟进去

    

     这里创建了一个线程工厂,主要是为线程设置名字、是否守护进程、线程的优先级等等。然后创建一个任务执行器,把线程工厂传进去赋给成员变量

     这个executor 后面在每个 事件执行器 创建子线程处理task来用

    接下来创建一个长度是nThreads的 EventExecutor[]  ,对于 子事件循环组来说,这里其实是创建了一个长度为8 的NioEventLoop的数组, 即 EventExecutor[]  children = new NioEventLoop[8]

    这个地方我纠结了一下,因为我语文太差了,我决定画个图来展示一下, 虽然我美术也不好。

    

    大家看下这个代码层级结构, 其实就很显而易见了,这里我要说一下,SingleThreadEventExecutor 中有一个thread成员变量,说明每个都只有一个线程来处理,并且含有任务队列和任务的执行器。

   另外每一个NioEventLoop都含有一个selector 多路复用器 。

   继续看,这里通过默认的选择工厂来创建一个选择器。

   

   跟进去,我们看到下面的这段代码,不得不感叹Netty真的已经把性能发挥到了极致,能用位运算的绝不会用数学计算法,所以这里对选择器进行了区分

  

   

    看这个判断方法,意思是 如果是 2的次方 ,那么创建一个 PowerOfTwoEventExecutorChooser 选择器

    我特意去验证了一个这个算法

    

   结果是:

    

   好了,讲到这里我们可以重新开始讲注册了,仍然进入  initAndRegister()方法

   

    config().group() 这个获取到的 是 ServerBootStrap.group(), 那么也就是取到了 父级的事件循环组 也就是bossGroup

 根据我上上图的分析,那么注册方法进入的肯定是 MultithreadEventLoopGroup 

   

  这里有一个next()方法,用来选择一个NioEventLoop。由于我这里是1个线程的数组,所以进入

  

  因此,对于bossGroup来说,就是 0 & 0 = 0   1 & 0 = 0  2 & 0 = 0 .....

            对于workerGroup来说,就是 0 & 7 = 0 1 & 7 = 1  2 & 7 = 2 .... 8 & 7 = 0  9 & 7 = 1 ....

 所以这里其实是一个轮询的算法。

 ok, 看到这里我们猜测是 从   new NioEventLoop[1]  中轮询一个 NioEventLoop, 然后把channel注册到上面的多路复用器上。

 继续看, 根据那个流程图,可以推断出是进入到  SingleThreadEventLoop

 

    接着传入了一个 DefaultChannelPromise ,用来做注册结果的异步通知的。传入了channel 和 当前的这个 SingleThreadEventLoop ,当然具体怎么异步通知的,我们后面会讲到

 

   继续看

  

  这里把刚刚选择出来的 NioEventLoop 赋给 Channel 的 eventLoop 的成员变量, 这里也就意味着 ,这个NioEventLoop 也将一直伴随 这个channel 的所有的读写操作, 因为通过上面的那个流程图表明了 一个NioEventLoop 上面只有一个Thread , 那么也可以得出 一个Channel 整个周期 内所有的读写操作,全部由同一个Thread来完成, 这也就说明了为什么Netty没有线程安全问题,当然随着后面的讲解,你将会对这个地方理解的更加的深刻。 

       好了,注册的内容我们下一节接着说。

추천

출처www.cnblogs.com/huxipeng/p/10994455.html