好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

Netty源码分析NioEventLoop初始化线程选择器创建

前文传送门: NioEventLoop创建

初始化线程选择器

回到上一小节的MultithreadEventExecutorGroup类的构造方法:

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

protected MultithreadEventExecutorGroup( int nThreads, Executor executor,

                                         EventExecutorChooserFactory chooserFactory, Object... args) {

     //代码省略

     if (executor == null ) {

         //创建一个新的线程执行器(1)

         executor = new ThreadPerTaskExecutor(newDefaultThreadFactory());

     }

     //构造NioEventLoop(2)

     children = new EventExecutor[nThreads];

     for ( int i = 0 ; i < nThreads; i ++) {

         boolean success = false ;

         try {

             children[i] = newChild(executor, args);

             success = true ;

         } catch (Exception e) {

             throw new IllegalStateException( "failed to create a child event loop" , e);

         } finally {

            //代码省略

         }

     }

     //创建线程选择器(3)

     chooser = chooserFactory.newChooser(children);

     //代码省略

}

我们看第三步, 创建线程选择器:

?

1

chooser = chooserFactory.newChooser(children);

NioEventLoop都绑定一个chooser对象, 作为线程选择器, 通过这个线程选择器, 为每一个channel分配不同的线程

我们看到newChooser(children)传入了NioEventLoop数组

我们跟到DefaultEventExecutorChooserFactory类中的newChooser方法:

?

1

2

3

4

5

6

7

public EventExecutorChooser newChooser(EventExecutor[] executors) {

     if (isPowerOfTwo(executors.length)) {

         return new PowerOfTowEventExecutorChooser(executors);

     } else {

         return new GenericEventExecutorChooser(executors);

     }

}

这里通过 isPowerOfTwo(executors.length) 判断NioEventLoop的线程数是不是2的倍数, 然后根据判断结果返回两种选择器对象, 这里使用到java设计模式的策略模式

根据这两个类的名字不难看出, 如果是2的倍数, 使用的是一种高性能的方式选择线程, 如果不是2的倍数, 则使用一种比较普通的线程选择方式

我们简单跟进这两种策略的选择器对象中看一下, 首先看一下PowerOfTowEventExecutorChooser这个类:

?

1

2

3

4

5

6

7

8

9

10

11

private static final class PowerOfTowEventExecutorChooser implements EventExecutorChooser {

     private final AtomicInteger idx = new AtomicInteger();

     private final EventExecutor[] executors;

     PowerOfTowEventExecutorChooser(EventExecutor[] executors) {

         this .executors = executors;

     }

     @Override

     public EventExecutor next() {

         return executors[idx.getAndIncrement() & executors.length - 1 ];

     }

}

这个类实现了线程选择器的接口EventExecutorChooser, 构造方法中初始化了NioEventLoop线程数组

重点关注下next()方法, next()方法就是选择下一个线程的方法, 如果线程数是2的倍数, 这里通过按位与进行计算, 所以效率极高

再看一下GenericEventExecutorChooser这个类:

?

1

2

3

4

5

6

7

8

9

10

11

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)];

     }

}

这个类同样实现了线程选择器的接口EventExecutorChooser, 并在造方法中初始化了NioEventLoop线程数组

再看这个类的next()方法, 如果线程数不是2的倍数, 则用绝对值和取模的这种效率一般的方式进行线程选择

这样, 我们就初始化了线程选择器对象

以上就是Netty源码分析NioEventLoop初始化线程选择器创建的详细内容,更多关于Netty线程选择器NioEventLoop的资料请关注其它相关文章!

原文链接:https://HdhCmsTestcnblogs测试数据/xiangnan6122/p/10202920.html

查看更多关于Netty源码分析NioEventLoop初始化线程选择器创建的详细内容...

  阅读:18次