Netty源码分析第二章: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
25 1protected MultithreadEventExecutorGroup(int nThreads, Executor executor,
2 EventExecutorChooserFactory chooserFactory, Object... args) {
3 //代码省略
4 if (executor == null) {
5 //创建一个新的线程执行器(1)
6 executor = new ThreadPerTaskExecutor(newDefaultThreadFactory());
7 }
8 //构造NioEventLoop(2)
9 children = new EventExecutor[nThreads];
10 for (int i = 0; i < nThreads; i ++) {
11 boolean success = false;
12 try {
13 children[i] = newChild(executor, args);
14 success = true;
15 } catch (Exception e) {
16 throw new IllegalStateException("failed to create a child event loop", e);
17 } finally {
18 //代码省略
19 }
20 }
21 //创建线程选择器(3)
22 chooser = chooserFactory.newChooser(children);
23 //代码省略
24}
25
我们看第三步
, 创建线程选择器
:
1
2 1chooser = chooserFactory.newChooser(children);
2
NioEventLoop
都绑定一个
chooser对象
, 作为线程选择器
, 通过这个线程选择器
, 为每一个
channel分配不同的线程
我们看到
newChooser(children)传入了
NioEventLoop数组
我们跟到
DefaultEventExecutorChooserFactory类中的
newChooser方法
:
1
2
3
4
5
6
7
8 1public EventExecutorChooser newChooser(EventExecutor[] executors) {
2 if (isPowerOfTwo(executors.length)) {
3 return new PowerOfTowEventExecutorChooser(executors);
4 } else {
5 return new GenericEventExecutorChooser(executors);
6 }
7}
8
这里通过
isPowerOfTwo(executors.length) 判断
NioEventLoop的线程数是不是
2的倍数
, 然后根据判断结果返回两种选择器对象
, 这里使用到
java设计模式的策略模式
根据这两个类的名字不难看出
, 如果是
2的倍数
, 使用的是一种高性能的方式选择线程
, 如果不是
2的倍数
, 则使用一种比较普通的线程选择方式
我们简单跟进这两种策略的选择器对象中看一下
, 首先看一下
PowerOfTowEventExecutorChooser这个类
:
1
2
3
4
5
6
7
8
9
10
11
12 1private static final class PowerOfTowEventExecutorChooser implements EventExecutorChooser {
2 private final AtomicInteger idx = new AtomicInteger();
3 private final EventExecutor[] executors;
4 PowerOfTowEventExecutorChooser(EventExecutor[] executors) {
5 this.executors = executors;
6 }
7 @Override
8 public EventExecutor next() {
9 return executors[idx.getAndIncrement() & executors.length - 1];
10 }
11}
12
这个类实现了线程选择器的接口
EventExecutorChooser, 构造方法中初始化了
NioEventLoop线程数组
重点关注下
next()方法
, next()方法就是选择下一个线程的方法
, 如果线程数是
2的倍数
, 这里通过按位与进行计算
, 所以效率极高
再看一下
GenericEventExecutorChooser这个类
:
1
2
3
4
5
6
7
8
9
10
11
12 1private static final class GenericEventExecutorChooser implements EventExecutorChooser {
2 private final AtomicInteger idx = new AtomicInteger();
3 private final EventExecutor[] executors;
4 GenericEventExecutorChooser(EventExecutor[] executors) {
5 this.executors = executors;
6 }
7 @Override
8 public EventExecutor next() {
9 return executors[Math.abs(idx.getAndIncrement() % executors.length)];
10 }
11}
12
这个类同样实现了线程选择器的接口
EventExecutorChooser, 并在造方法中初始化了
NioEventLoop线程数组
再看这个类的
next()方法
, 如果线程数不是
2的倍数
, 则用绝对值和取模的这种效率一般的方式进行线程选择
这样
, 我们就初始化了线程选择器对象
上一节: NioEventLoopGroup之NioEventLoop的创建
下一节: NioEventLoop线程启动