其实在将这一节之前,我们来分析一个东西,方便下面的工作好开展。

打开启动类,最开始的时候创建了一个NioEventLoopGroup 事件循环组,我们来跟一下这个。

这里bossGroup, 我传入了一个线程, workerGroup 没有入参,默认0, 也就是说父级我用一个线程来处理客户端的接入, 多个线程来处理客户端的读写操作

通过一连串的构造方法进入到

executor 是 null , selectorProvider 用来创建一个多路复用器, 最后一个参数传入了 一个多路复用器的一个策略, 这个策略我们后面会讲到

紧接着又传入了一个拒绝策略, 由于  NioEventLoopGroup 继承了 MultithreadEventLoopGroup,所以进入 MultithreadEventLoopGroup 的构造方法

这里的判断, bossGroup 传入了 1 ,所以nThreads = 1;  workerGroup 没有入参,默认是0 ,所以这里到了一个判断默认线程数的地方。

就是这了, NettyRuntime.availableProcessors() * 2  代表 CPU核心数 * 2(处理器超线程数) * 2的值  或  CPU数 * 2的值

在cmd命令中输入“wmic”,然后在出现的新窗口中输入“cpu get *”。
     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没有线程安全问题,当然随着后面的讲解,你将会对这个地方理解的更加的深刻。

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

Netty源码分析--Channel注册(上)(五)的更多相关文章

  1. Netty源码分析--Channel注册(中)(六)

    接上一篇,我们继续看 不知道大家第一次看这段代码的时候有没有一脸懵逼,反正我是一脸懵,为什么这个if else 最终都是调用的register0方法,都是一样的. 其实这里就是为什么Netty是线程安 ...

  2. Netty源码分析--Channel注册&绑定端口(下)(七)

    接下来,我们看到的就是两个非常重要的方法 就是 processSelectedKeys() 和  runAllTasks() 方法了. selectionKey中ready的事件,如accept.co ...

  3. Netty源码分析-- 处理客户端接入请求(八)

    这一节我们来一起看下,一个客户端接入进来是什么情况.首先我们根据之前的分析,先启动服务端,然后打一个断点. 这个断点打在哪里呢?就是NioEventLoop上的select方法上. 然后我们启动一个客 ...

  4. Netty源码分析第1章(Netty启动流程)---->第3节: 服务端channel初始化

    Netty源码分析第一章:Netty启动流程   第三节:服务端channel初始化 回顾上一小节的initAndRegister()方法: final ChannelFuture initAndRe ...

  5. Netty源码分析第1章(Netty启动流程)---->第4节: 注册多路复用

    Netty源码分析第一章:Netty启动流程   第四节:注册多路复用 回顾下以上的小节, 我们知道了channel的的创建和初始化过程, 那么channel是如何注册到selector中的呢?我们继 ...

  6. Netty源码分析第3章(客户端接入流程)---->第4节: NioSocketChannel注册到selector

    Netty源码分析第三章: 客户端接入流程 第四节: NioSocketChannel注册到selector 我们回到最初的NioMessageUnsafe的read()方法: public void ...

  7. Netty源码分析--内存模型(上)(十一)

    前两节我们分别看了FastThreadLocal和ThreadLocal的源码分析,并且在第八节的时候讲到了处理一个客户端的接入请求,一个客户端是接入进来的,是怎么注册到多路复用器上的.那么这一节我们 ...

  8. Netty源码分析第1章(Netty启动流程)---->第5节: 绑定端口

    Netty源码分析第一章:Netty启动步骤 第五节:绑定端口 上一小节我们学习了channel注册在selector的步骤, 仅仅做了注册但并没有监听事件, 事件是如何监听的呢? 我们继续跟第一小节 ...

  9. Netty源码分析第3章(客户端接入流程)---->第5节: 监听读事件

    Netty源码分析第三章: 客户端接入流程 第五节: 监听读事件 我们回到AbstractUnsafe的register0()方法: private void register0(ChannelPro ...

随机推荐

  1. 经典书单、站点 —— 大数据/数据分析/R语言

    1. 科普.入门 <大数据智能>,刘知远.崔安顺等著: 特色:系统,宏观和全面: 2. R 语言站点 http://langdawei.com/:R 语言数据采集与可视化:

  2. Python 辨异 —— __init__ 与 __new__

    __init__ 更多的作用是初始化属性,__new__ 进行的是创建对象,显然 __new__ 要早于 __init__ 发生. 考虑一个继承自 tuple 的类,显然在 __init__ 无法对其 ...

  3. python中对文件、文件夹的操作

    python中对文件.文件夹的操作需要涉及到os模块和shutil模块. 创建文件: 1) os.mknod("test.txt")       创建空文件 2) open(&qu ...

  4. 微信小程序之加载更多(分页加载)实例

    业务需求: 列表滚动到底部时,继续往上拉,加载更多内容 必备参数: (1)pageindex: 1 //第几次加载 (2)callbackcount: 15 //需要返回数据的个数 其他参数: 根据接 ...

  5. Asp.net-MyFirstMVCProject详细解释

    一个URL要求, ASP.NET MVC引擎将分析URL要使用Controller, 这个Controller(取而代之的是,真实的方法Controller的Action)从数据库或者其它数据源获取数 ...

  6. bigdata_ Kafka集群模式部署

    环境:kafka 0.8.1.1 基本概念 Kafka维护按类区分的消息,称为主题(topic) 生产者(producer)向kafka的主题发布消息 消费者(consumer)向主题注册,并且接收发 ...

  7. UVE开发环境搭建及项目启动

    1.IDE安装visual studio code ,略: 2.node安装(node-v10.5.0-win-x64.zip),解压即可: 3.配置node环境变量,cmd 输入node -v.np ...

  8. [WPF]有Focus(), 那Unfocus()呢?

    原文:[WPF]有Focus(), 那Unfocus()呢? [WPF]有Focus(), 那Unfocus()呢? 周银辉 我们可以调用Focus()方法,让WPF控件获得焦点, 那我现在不想要焦点 ...

  9. WPF 播放音频使用的SoundPlayer和MediaPlayer

    WPF中,最简单最容易播放音频的方式是使用SoundPlayer类.它是.NET Framework 2.0的一部分,是对Win32 PlaySound API的封装. 它具有以下限制: 1)仅支持. ...

  10. 投资人的能量往往大多远远不仅于此,他能站在不同的角度和高度看问题(要早点拿投资,要舍得让出股份)——最好不要让 Leader 一边做技术、一边做管理,人的能力是有限的,精力也是有限的

      摘要:在创业三年时间里作为联合创始人,虽然拿着大家均等的股份,我始终是没有什么话语权的,但是,这也给了我从旁观者的角度看清整个局面的机会.创业公司的成败绝大程度取决于技术大牛和公司 Leader, ...