Netty 源码分析1.2 NioEventLoopGroup创建逻辑

========= 本系统文章都是依据Netty的4.1.44.Final-SNAPSHOT这个版本来讲解====================

本文中关联的所有文章的总目录可以参看系列文章目录

      在前面一章中已经简单的了解了一个socket的代码结构,用了哪些类?那么我们就先了解下使用到的NioEventLoopGroup这个类

1.类的继承关系图

在这里插入图片描述
      可以看出该类本身实际上是一个可以定时执行任务的线程池。我们在创建ServerBootstrap 类时一般设置父的EventLoopGroup 接收连接的池组时,都是使用的NioEventLoopGroup类,而处理连接后的数据处理的也是NioEventLoopGroup类。而具体该类的作用我们会分为几步来查看业务:
      第一步就是创建该类时所做的业务;
      第二步就是在ServerBootstrap 类在bind()时会调用register方法

2.创建类时代码执行的逻辑

2.1 序列图

      首先通过序列图我们大致了解下NioEventGroup类主要做些什么?
在这里插入图片描述

2.1.1 具体说明其中一些步骤的内容

  1. EventExecutor[] 数组
           在第17步中事件执行选择工厂类在创建选择器时,使用了两种不同的选择方式,与创建的EventExecutor数组的长度有关(在上图中第8步创建的默认的数组长度),而这个长度是由使用者来决定的,一般有两种方式;
          1) 当我们在创建NioEventLoopGroup类是传入了线程个数,那么就是以这个线程个数为准(线程个数必须要大于0 );
          2)如果没有传入时系统会默认设置;

  2. 后面我们看下默认设置的方式是:
          如果使用的是空的构建方法或者设置的值是0时
          new NioEventLoopGroup();
          new NioEventLoopGroup(0);
          NioEventLoopGroup 在其父类MultithreadEventLoopGroup 中会对线程个数进行设置;设置EventExecutor数组个数值的代码如下所示:
    在这里插入图片描述

其中SystemPropertyUtil.getInt的处理逻辑就是
      首先它会通过**System.getProperty(“io.netty.eventLoopThreads”)**从系统变量中取,如果取不到,然后默认为NettyRuntime.availableProcessors() * 2 个线程数
      而NettyRuntime.availableProcessors()的处理它实际调用的是 :

SystemPropertyUtil.getInt(“io.netty.availableProcessors”,Runtime.getRuntime().availableProcessors());

方法,到此我们理清了这个逻辑:
      1)首先如果用户设置了io.netty.eventLoopThreads 系统变量值,那么就以该值为准(如果该值大于1);
      2)没有设置,再看用户是否设置了io.netty.availableProcessors系统变量值,如果设置了就以该值为准;如果没有设置那么就以当前服务器的处理器核数为准;

  1. 回过头来,我们再看第17步中的EventExecutor选择器的两种处理方式:
    EventExecutorChooserFactory.EventExecutorChooser 实际是DefaultEventExecutorChooseFactory来实现的,而它内部创建这个对象的具体操作逻辑是:
          1)当是2的指数次幂时(具体的算法可以参看我写的学习点中: Netty源码中知识点学习记录----2的指数次幂),选择下一个EventExecutor的处理类是PowerOfTwoEventExecutorChooser,它的处理方式如下所示:

private static final class PowerOfTwoEventExecutorChooser implements EventExecutorChooser {
        private final AtomicInteger idx = new AtomicInteger();
        private final EventExecutor[] executors;

        PowerOfTwoEventExecutorChooser(EventExecutor[] executors) {
            this.executors = executors;
        }

        @Override
        public EventExecutor next() {
            return executors[idx.getAndIncrement() & executors.length - 1];
        }
    }

      也就是说当EventExecutor的数组长度是2的指数次幂时,每到数组的长度换一个EventExecutor对象。

      2)当不是2的指数次幂时,选择下一个EventExecutor的处理类是GenericEventExecutorChooser,它的处理方式如下所示:

private static final class GenericEventExecutorChooser implements EventExecutorChooser {
        private final AtomicInteger idx = new AtomicInteger();
        private final EventExecutor[] executors;

        GenericEventExecutorChooser(EventExecutor[] executors) {
            this.executors = executors;
        }

        @Override
        public EventExecutor next() {
            return executors[Math.abs(idx.getAndIncrement() % executors.length)];
        }
    }

      因为idx AtomicInteger,它内部存储的实际上就是一个int数值, 所以上面两种类处理方式的唯一区别就是当idx的值超过int范围值进入负数时,PowerOfTwoEventExecutorChooser 类还是每增长一位从数组的下标0开始,然后到[数组长度-1]这样循环,而GenericEventExecutorChooser类当到int最小值时,它是从[数组长度-1]取,然后下标依次递减,这样重复执行;

  1. 通过序列图分析出该类中具体的属性赋值情况如下所示:
类名属性类型属性名赋值
MultithreadEventLoopGroupintDEFAULT_EVENT_LOOP_THREADS默认是处理器的2倍
MultithreadEventExecutorGroupEventExecutor[]children数组中放入的都是NioEventLoop类
MultithreadEventExecutorGroupSetreadonlyChildren放入的就是EventExecutor[]中存储的元素,用UnmodifiableSet这个只读的集合重新封装了下
MultithreadEventExecutorGroupEventExecutorChooserFactory.EventExecutorChooserchooserDefaultEventExecutorChooserFactory来创建的,根据children数组的长度有关

==============================================================================
后续文章还在编写中:下一篇是 Netty 源码分析一ServerBootstrap的bind方法

讲解这个方法是可以引出来NioEventLoopGroup在ServerBootstrap这个类中做了哪些事?

文章讲解的过程中,我们可以看到这些工具类:
SystemPropertyUtil----- 主要是对System.getProperty 进行封装
NettyRuntime -------主要是对Runtime.getRuntime().availableProcessors() 进行包装处理

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值