Netty源码分析第二章:NioEventLoop

 

第三节:初始化线程选择器

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

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);
//代码省略
}

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

chooser = chooserFactory.newChooser(children);

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

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

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

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这个类:

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这个类:

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的倍数, 则用绝对值和取模的这种效率一般的方式进行线程选择

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

上一节: NioEventLoopGroup之NioEventLoop的创建

下一节: NioEventLoop线程启动

Netty源码分析第2章(NioEventLoop)---->第3节: 初始化线程选择器的更多相关文章

  1. Netty源码分析第2章(NioEventLoop)---->第1节: NioEventLoopGroup之创建线程执行器

    Netty源码分析第二章: NioEventLoop 概述: 通过上一章的学习, 我们了解了Server启动的大致流程, 有很多组件与模块并没有细讲, 从这个章开始, 我们开始详细剖析netty的各个 ...

  2. Netty源码分析第2章(NioEventLoop)---->第2节: NioEventLoopGroup之NioEventLoop的创建

    Netty源码分析第二章: NioEventLoop   第二节: NioEventLoopGroup之NioEventLoop的创建 回到上一小节的MultithreadEventExecutorG ...

  3. Netty源码分析第2章(NioEventLoop)---->第4节: NioEventLoop线程的启动

    Netty源码分析第二章: NioEventLoop   第四节: NioEventLoop线程的启动 之前的小节我们学习了NioEventLoop的创建以及线程分配器的初始化, 那么NioEvent ...

  4. Netty源码分析第2章(NioEventLoop)---->第5节: 优化selector

    Netty源码分析第二章: NioEventLoop   第五节: 优化selector 在剖析selector轮询之前, 我们先讲解一下selector的创建过程 回顾之前的小节, 在创建NioEv ...

  5. Netty源码分析第2章(NioEventLoop)---->第6节: 执行select操作

    Netty源码分析第二章: NioEventLoop   第六节: 执行select操作 分析完了selector的创建和优化的过程, 这一小节分析select相关操作 跟到跟到select操作的入口 ...

  6. Netty源码分析第2章(NioEventLoop)---->第7节: 处理IO事件

    Netty源码分析第二章: NioEventLoop   第七节:处理IO事件 上一小节我们了解了执行select()操作的相关逻辑, 这一小节我们继续学习select()之后, 轮询到io事件的相关 ...

  7. Netty源码分析第2章(NioEventLoop)---->第8节: 执行任务队列

      Netty源码分析第二章: NioEventLoop   第八节: 执行任务队列 继续回到NioEventLoop的run()方法: protected void run() { for (;;) ...

  8. Netty源码分析第4章(pipeline)---->第7节: 前章节内容回顾

    Netty源码分析第四章: pipeline 第七节: 前章节内容回顾 我们在第一章和第三章中, 遗留了很多有关事件传输的相关逻辑, 这里带大家一一回顾 首先看两个问题: 1.在客户端接入的时候, N ...

  9. Netty源码分析第5章(ByteBuf)---->第10节: SocketChannel读取数据过程

    Netty源码分析第五章: ByteBuf 第十节: SocketChannel读取数据过程 我们第三章分析过客户端接入的流程, 这一小节带大家剖析客户端发送数据, Server读取数据的流程: 首先 ...

随机推荐

  1. 清除SQL server 记住的用户名和密码

    公司更换电脑,清除SQL server 记住的用户名和密码 请按照上图中的位置找到相应的文件SqlStudio.bin,然后把它删除,请放一百个心,这个文件会自动生成的. 需要注意的是,在删除之前一定 ...

  2. 20165302 敏捷开发与XP实践作业

    20165302 敏捷开发与XP实践实验报告 一.提交点一 1.实验要求 参考 http://www.cnblogs.com/rocedu/p/6371315.html#SECCODESTANDARD ...

  3. NYOJ 18 The Triangle 填表法,普通dp

    题目链接: http://acm.nyist.edu.cn/JudgeOnline/problem.php?pid=18 The Triangle 时间限制:1000 ms  |  内存限制:6553 ...

  4. Use UMDH to identify memory leak problem

    We sometimes got memory leak problem, and we need to find the leaked memory, Here is a usful tool fr ...

  5. django之models学习总结

    from django.db import models # Create your models here. class Classes(models.Model): ''' 班级表 ''' tit ...

  6. hadoop环境搭建-伪分布模式

    Appache hadoop 版本:2.77   jdk:1.8  系统:centos7 注意不要在root下解压,要单独建一个用户安装hadoop及其组件. 一.先查看系统是否有自带j #dk: r ...

  7. UWP 播放直播流 3MU8

    UWP 播放直播流 3MU8 参考:http://www.c-sharpcorner.com/UploadFile/2b876a/http-live-streaming-in-windows-10-u ...

  8. BZOJ2120_数颜色_KEY

    题目传送门 裸的带修莫队. 在Sort时如果左右区间都在同一块中,就按询问的修改的先后Sort. 对于每次查询判断向前或向后修改. 当size为N*2/3时据说是最优.O(N^(3/5)). code ...

  9. Why network port is open but no process attached?(为什么端口被打开,但是没有进程号)

    When I check my system today, I noticed a weird output from netstat’s output, joseph# sudo netstat - ...

  10. CF 1114 D. Flood Fill

    D. Flood Fill 链接 题意: 一个颜色序列,每个位置有一个颜色,选择一个起始位置,每次可以改变包含这个位置的颜色段,将这个颜色段修改为任意一个颜色, 问最少操作多少次.n<=5000 ...