Netty源码分析(四):EventLoopGroup
无论服务端或客户端启动时都用到了
NioEventLoopGroup,从名字就可以看出来它是NioEventLoop的组合,是Netty多线程的基石。
类结构
NioEventLoopGroup继承自MultithreadEventLoopGroup,多提供了两个方法setIoRatio和rebuildSelectors,一个用于设置NioEventLoop用于IO处理的时间占比,另一个是重新构建Selectors,来处理epoll空轮询导致CPU100%的bug。这个两个的用处在介绍NioEventLoop的时候在详细介绍。其它的方法都在接口中有定义,先看下EventExecutorGroup。
EventExecutorGroup
EventExecutorGroup继承自ScheduledExecutorService和Iterable。这意味着EventExecutorGroup拥有定时处理任务的能力,同时本身可以迭代。它提供的方法有:
/**
* 是否所有事件执行器都处在关闭途中或关闭完成
*/
boolean isShuttingDown();
/**
* 优雅关闭
*/
Future<?> shutdownGracefully();
Future<?> shutdownGracefully(long quietPeriod, long timeout, TimeUnit unit);
/**
* 返回线程池终止时的异步结果
*/
Future<?> terminationFuture();
void shutdown();
List<Runnable> shutdownNow();
/**
* 返回一个事件执行器
*/
EventExecutor next();
其中shutdown和shutdownNow被标记为过时,不建议使用。EventExecutorGroup还重写ScheduledExecutorService接口的方法,用于返回自定义的Future。
EventLoopGroup
EventLoopGroup继承自EventExecutorGroup,它和EventExecutorGroup想比多了注册Channel和ChannelPromise,同时重新next方法返回EventLoop。
MultithreadEventExecutorGroup
创建NioEventLoopGroup时,最终都会调用MultithreadEventExecutorGroup的构造方法。
protected MultithreadEventExecutorGroup(int nThreads, Executor executor,
EventExecutorChooserFactory chooserFactory, Object... args) {
// 线程数必须大于0
if (nThreads <= 0) {
throw new IllegalArgumentException(String.format("nThreads: %d (expected: > 0)", nThreads));
}
// 没指定Executor就创建新的Executor
if (executor == null) {
executor = new ThreadPerTaskExecutor(newDefaultThreadFactory());
}
// 创建EventExecutor数组
children = new EventExecutor[nThreads];
for (int i = 0; i < nThreads; i++) {
// 创建结果标识
boolean success = false;
try {
// 创建EventExecutor对象
children[i] = newChild(executor, args);
// 设置创建成功
success = true;
} catch (Exception e) {
throw new IllegalStateException("failed to create a child event loop", e);
} finally {
// 创建失败,关闭所有已创建的EventExecutor
if (!success) {
// 关闭所有已创建的EventExecutor
for (int j = 0; j < i; j++) {
children[j].shutdownGracefully();
}
// 确保所有已创建的EventExecutor已关闭
for (int j = 0; j < i; j++) {
EventExecutor e = children[j];
try {
while (!e.isTerminated()) {
e.awaitTermination(Integer.MAX_VALUE, TimeUnit.SECONDS);
}
} catch (InterruptedException interrupted) {
// Let the caller handle the interruption.
Thread.currentThread().interrupt();
break;
}
}
}
}
}
// 创建EventExecutor选择器
chooser = chooserFactory.newChooser(children);
// 创建监听器,用于EventExecutor终止时的监听
final FutureListener<Object> terminationListener = new FutureListener<Object>() {
@Override
public void operationComplete(Future<Object> future) throws Exception {
// 当EventExecutor全部关闭时
if (terminatedChildren.incrementAndGet() == children.length) {
// 设置结果,并通知监听器们。
terminationFuture.setSuccess(null);
}
}
};
// 给每个EventExecutor添加上监听器
for (EventExecutor e : children) {
e.terminationFuture().addListener(terminationListener);
}
// 创建只读的EventExecutor集合
Set<EventExecutor> childrenSet = new LinkedHashSet<EventExecutor>(children.length);
Collections.addAll(childrenSet, children);
readonlyChildren = Collections.unmodifiableSet(childrenSet);
}
整个构造方法做的就是EventExecutor的创建,包括创建的异常处理,成功通知等。
AbstractEventExecutorGroup、MultithreadEventLoopGroup和NioEventLoopGroup内部没有特殊之处,就不拓展了。
文中帖的代码注释全在:KAMIJYOUDOUMA, 有兴趣的童鞋可以关注一下。
本篇到此结束,如果读完觉得有收获的话,欢迎点赞、关注、加公众号【贰级天災】,查阅更多精彩历史!!!
Netty源码分析(四):EventLoopGroup的更多相关文章
- [编织消息框架][netty源码分析]5 EventLoopGroup 实现类NioEventLoopGroup职责与实现
分析NioEventLoopGroup最主有两个疑问 1.next work如何分配NioEventLoop 2.boss group 与child group 是如何协作运行的 从EventLoop ...
- Netty源码分析第1章(Netty启动流程)---->第1节: 服务端初始化
Netty源码分析第一章: Server启动流程 概述: 本章主要讲解server启动的关键步骤, 读者只需要了解server启动的大概逻辑, 知道关键的步骤在哪个类执行即可, 并不需要了解每一步的 ...
- Netty源码分析第1章(Netty启动流程)---->第4节: 注册多路复用
Netty源码分析第一章:Netty启动流程 第四节:注册多路复用 回顾下以上的小节, 我们知道了channel的的创建和初始化过程, 那么channel是如何注册到selector中的呢?我们继 ...
- Netty源码分析第4章(pipeline)---->第7节: 前章节内容回顾
Netty源码分析第四章: pipeline 第七节: 前章节内容回顾 我们在第一章和第三章中, 遗留了很多有关事件传输的相关逻辑, 这里带大家一一回顾 首先看两个问题: 1.在客户端接入的时候, N ...
- netty源码分析(十八)Netty底层架构系统总结与应用实践
一个EventLoopGroup当中会包含一个或多个EventLoop. 一个EventLoop在它的整个生命周期当中都只会与唯一一个Thread进行绑定. 所有由EventLoop所处理的各种I/O ...
- Netty源码分析(前言, 概述及目录)
Netty源码分析(完整版) 前言 前段时间公司准备改造redis的客户端, 原生的客户端是阻塞式链接, 并且链接池初始化的链接数并不高, 高并发场景会有获取不到连接的尴尬, 所以考虑了用netty长 ...
- 【转】netty源码分析之LengthFieldBasedFrameDecoder
原文:https://www.jianshu.com/p/a0a51fd79f62 拆包的原理 关于拆包原理的上一篇博文 netty源码分析之拆包器的奥秘 中已详细阐述,这里简单总结下:netty的拆 ...
- Netty源码分析第1章(Netty启动流程)---->第2节: NioServerSocketChannel的创建
Netty源码分析第一章: Server启动流程 第二节:NioServerSocketChannel的创建 我们如果熟悉Nio, 则对channel的概念则不会陌生, channel在相当于一个通 ...
- Netty源码分析第1章(Netty启动流程)---->第3节: 服务端channel初始化
Netty源码分析第一章:Netty启动流程 第三节:服务端channel初始化 回顾上一小节的initAndRegister()方法: final ChannelFuture initAndRe ...
- Netty源码分析第2章(NioEventLoop)---->第1节: NioEventLoopGroup之创建线程执行器
Netty源码分析第二章: NioEventLoop 概述: 通过上一章的学习, 我们了解了Server启动的大致流程, 有很多组件与模块并没有细讲, 从这个章开始, 我们开始详细剖析netty的各个 ...
随机推荐
- copy与mutableCopy的区别总结
1.不可变类型(不管是集合还是非集合),copy结果,不产生新对象,浅拷贝:不可变类型(不管是集合还是非集合),mutableCopy结果,产生新对象,深拷贝.2.可变类型(不管是集合还是非集合),c ...
- 学习--->更新集合/内存/深浅拷贝
一.计算机基础 1..软件(应用程序) 2.解释器/编译器 - 解释型语言:将代码每一行传递给计算机一行,常用编程语言python,PHP,Ruby. - 编译型语言:将代码完全执行完后会形成一个文 ...
- Egret获取和显示时间,年,月,日,时分秒
let now = new Date(); this.nowYear = now.getFullYear(); this.nowMonth = now.getMonth() + 1; let noww ...
- 如何使用$.each()与$().each()以及他们的区别
1.首先,说下$.each(Arry/Object,function(index,val){ //index表示下标,val表示下标对应的值 }) 下面是使用$.each()的几种类型,其中arr2与 ...
- Codeforces Round #555 (Div. 3) AB
A: http://codeforces.com/contest/1157/problem/A 题意:每次加到10的整数倍之后,去掉后面的0,问最多有多少种可能. #include <io ...
- Java课程之团队开发(NABCD需求分析)
N.需求 1.学生基本的录入课程功能 2.学生对于空教室使用的需求(自习或者是活动占用) 3.学生对于具体课程的查询需求 A.做法 1.制作出基于安卓的课程查询,录入以及教室查询应用软件 B.好处 1 ...
- pyhton 监听文件输入实例
def tail(filename): f = open(filename,encoding='utf-8') while True: line = f.readline() if line.stri ...
- VIM常用快捷键(转载)
移动光标 h,j,k,l 上,下,左,右 ctrl-e 移动页面 ctrl-f 上翻一页 ctrl-b 下翻一页 ctrl-u 上翻半页 ctrl-d 下翻半页 w 跳到下一个字首,按标点或单词分割 ...
- c++ 读取不了hdf5文件中的字符串
问题描述: 在拿到一个hdf5文件,想用c++去读取文件中的字符串,但是会报错:read failed ps: c++读取hdf5的字符串方法见:https://support.hdfgroup.or ...
- Python练手例子(15)
85.输入一个奇数,然后判断最少几个 9 除于该数的结果为整数. 程序分析:999999 / 13 = 76923. #!/usr/bin/python #coding=utf-8 if __name ...