Netty源码分析第2章(NioEventLoop)—->第3节: 初始化线程选择器

释放双眼,带上耳机,听听看~!

 

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线程启动

 

给TA打赏
共{{data.count}}人
人已打赏
安全技术

Bootstrap 间隔 (Spacing)

2021-12-21 16:36:11

安全技术

从零搭建自己的SpringBoot后台框架(二十三)

2022-1-12 12:36:11

个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
搜索