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. AbstractApplicationContext 笔记

    一.这个类的属性 public abstract class AbstractApplicationContext extends DefaultResourceLoader implements C ...

  2. 基于PHP的cURL快速入门教程 (小偷采集程序)

    cURL 是一个利用URL语法规定来传输文件和数据的工具,支持很多协议,如HTTP.FTP.TELNET等.很多小偷程序都是使用这个函数.     最爽的是,PHP也支持 cURL 库.本文将介绍 c ...

  3. App-IOS与Android弱网环境测试

    弱网环境下App的功能是否正常使用,是否会发生Crash的等情况? 1.IOS ios系统一般自带弱网环境测试,可以通过设置各种网络环境,模拟弱网环境,如3G,wifi,very bad Networ ...

  4. python获取网站http://www.weather.com.cn 城市 8-15天天气

    参考一个前辈的代码,修改了一个案例开始学习beautifulsoup做爬虫获取天气信息,前辈获取的是7日内天气, 我看旁边还有8-15日就模仿修改了下.其实其他都没有变化,只变换了获取标签的部分.但是 ...

  5. Jmeter之post上传文件

    上周五东西都收拾好了,然后被叫住加班,直接搞到凌晨一两点,原因是另一个项目的性能出了点问题.为此我抓包写了一下主业务流的接口,涉及到文件上传,记录一下吧. 一.创建线程组,添加各类组件 这个就不用说了 ...

  6. JavaScript小例子

    1. alert.html <html> <head> <title></title> <script type="text/javas ...

  7. 第一章 Linux内核简介

    1. 操作系统和内核 操作系统是指在整个系统中负责完成最基本功能和系统管理的那些部分.包括内核.设备驱动程序.启动引导程序.命令行shell或者其他种类的用户界面.基本的文件管理工具和系统工具. 用户 ...

  8. 文本处理三剑客之 awk

    GAWK:报告生成器,格式化文本输出 awk [options] ‘program’ var=value file… awk [options] -f programfile var=value fi ...

  9. 浏览器与go语言的websocket通信

    简介WebSocket是HTML5一种新的协议.顾名思义,它在服务器和浏览器之间建立了全双工通信. 需求背景区块链测试系统web前端平台需要动态接收后端发送的状态信息改变一次测试session过程的状 ...

  10. 【转载】WCF 客户端识别认证之UserName认证

    原文地址: http://blog.csdn.net/zxz414644665/article/details/9308055 过程:用户调用service,服务端验证用户传来的用户名和密码(传输过程 ...