netty核心组件之EventLoopGroup和EventLoop
这节我们着重介绍netty最为核心的组件EventLoopGroup和EventLoop
EventLoopGroup:顾名思义就是EventLoop的组,下面来看它们的继承结构


在netty中我们可以把EventLoop看做一个线程,当然线程不单是jdk中的的线程,它们都从Executor一路继承过来,NioEventLoop继承SinfleThreadEventLoop,从名字可以看出它是一个单线程的EventLoop,
我们先来看NioEventLoop是如何构造的
public NioEventLoopGroup() {
this(0);
}
public NioEventLoopGroup(int nThreads) {
this(nThreads, (Executor) null);
}
~~~~~~~~~~~~~
public NioEventLoopGroup(int nThreads, Executor executor, EventExecutorChooserFactory chooserFactory,
final SelectorProvider selectorProvider,
final SelectStrategyFactory selectStrategyFactory,
final RejectedExecutionHandler rejectedExecutionHandler) {
super(nThreads, executor, chooserFactory, selectorProvider, selectStrategyFactory, rejectedExecutionHandler);
}
NioEventLoop构造函数非常多,每个参数都可以定制,我就不全贴出来了,最后回到这个参数最全的构造函数,下面我们挨个解释每个参数的作用
- nThreads: 线程数,对应EventLoop的数量,为0时 默认数量为CPU核心数*2
- executor: 这个我们再熟悉不过,最终用来执行EventLoop的线程
- chooserFactor: 当我们提交一个任务到线程池,chooserFactor会根据策略选择一个线程来执行
- selectorProvider:用来实例化jdk中的selector,没一个EventLoop都有一个selector
- selectStrategyFactory:用来生成后续线程运行时对应的选择策略工厂
- rejectedExecutionHandler:跟jdk中线程池中的作用一样,用于处理线程池没有多余线程的情况,默认直接抛出异常
接着我们进入父类MultithreadEventLoopGroup的构造函数
protected MultithreadEventExecutorGroup(int nThreads, Executor executor,
EventExecutorChooserFactory chooserFactory, Object... args) {
if (nThreads <= 0) {
throw new IllegalArgumentException(String.format("nThreads: %d (expected: > 0)", nThreads));
} if (executor == null) {
executor = new ThreadPerTaskExecutor(newDefaultThreadFactory());
}
// 创建nThreads大小的EventLoop数组
children = new EventExecutor[nThreads]; for (int i = 0; i < nThreads; i ++) {
boolean success = false;
try {
// 创建具体的EventLoop,会调用子类NioEventLoopGruop中的方法
children[i] = newChild(executor, args);
success = true;
} catch (Exception e) {
// TODO: Think about if this is a good exception type
throw new IllegalStateException("failed to create a child event loop", e);
} finally {
if (!success) {
// 如果其中有一个创建失败,把之前创建好的都关闭掉
for (int j = 0; j < i; j ++) {
children[j].shutdownGracefully();
} 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;
}
}
}
}
}
// 把刚才创建好的EventLoop提供给EventExecutorChooser,用于后续选择
chooser = chooserFactory.newChooser(children); // 添加一个EventLoop监听器,用来监听EventLoop终止状态
final FutureListener<Object> terminationListener = new FutureListener<Object>() {
@Override
public void operationComplete(Future<Object> future) throws Exception {
if (terminatedChildren.incrementAndGet() == children.length) {
terminationFuture.setSuccess(null);
}
}
}; for (EventExecutor e: children) {
// 循环加入
e.terminationFuture().addListener(terminationListener);
}
// 将EventLoop数组转成一个只读的set
Set<EventExecutor> childrenSet = new LinkedHashSet<EventExecutor>(children.length);
Collections.addAll(childrenSet, children);
readonlyChildren = Collections.unmodifiableSet(childrenSet);
}
我们继续跟到父类NioEventLoopGroup中的newChild
protected EventLoop newChild(Executor executor, Object... args) throws Exception {
return new NioEventLoop(this, executor, (SelectorProvider) args[0],
((SelectStrategyFactory) args[1]).newSelectStrategy(), (RejectedExecutionHandler) args[2]);
}
可以看出先用来创建EventLoopGroup的参数其实都是用来创建EventLoop的,我们继续跟NioEventLoop的构造
NioEventLoop(NioEventLoopGroup parent, Executor executor, SelectorProvider selectorProvider,
SelectStrategy strategy, RejectedExecutionHandler rejectedExecutionHandler) {
super(parent, executor, false, DEFAULT_MAX_PENDING_TASKS, rejectedExecutionHandler);
if (selectorProvider == null) {
throw new NullPointerException("selectorProvider");
}
if (strategy == null) {
throw new NullPointerException("selectStrategy");
}
provider = selectorProvider;
// 创建selector,由此可见每一个EventLoop都会有一个selector
final SelectorTuple selectorTuple = openSelector();
selector = selectorTuple.selector;
unwrappedSelector = selectorTuple.unwrappedSelector;
selectStrategy = strategy;
} protected SingleThreadEventExecutor(EventExecutorGroup parent, Executor executor,
boolean addTaskWakesUp, int maxPendingTasks,
RejectedExecutionHandler rejectedHandler) {
super(parent);
this.addTaskWakesUp = addTaskWakesUp;
this.maxPendingTasks = Math.max(16, maxPendingTasks);
this.executor = ObjectUtil.checkNotNull(executor, "executor");
// 用来添加task的阻塞队列 链表结构
taskQueue = newTaskQueue(this.maxPendingTasks);
rejectedExecutionHandler = ObjectUtil.checkNotNull(rejectedHandler, "rejectedHandler");
}
这里我们只是创建EventLoop,同时设置了执行的线程池、selector、taskQueue,并添加一个监听器用来监听它们的关闭状态,当所有线程都全部处于关闭状态terminationFuture会被置为true,到此还是没有实际创建可执行的thread。
后续我们在介绍channel的时候就知道EventLoop和channel如何建立关系,什么时候执行线程,我们姑且把EventLoop当做一个可执行runnable的netty线程
netty核心组件之EventLoopGroup和EventLoop的更多相关文章
- Netty 核心组件 EventLoop 源码解析
前言 在前文 Netty 启动过程源码分析 (本文超长慎读)(基于4.1.23) 中,我们分析了整个服务器端的启动过程.在那篇文章中,我们重点关注了启动过程,而在启动过程中对核心组件并没有进行详细介绍 ...
- 【Netty】Netty核心组件介绍
一.前言 前篇博文体验了Netty的第一个示例,下面接着学习Netty的组件和其设计. 二.核心组件 2.1. Channel.EventLoop和ChannelFuture Netty中的核心组件包 ...
- Netty核心组件介绍及手写简易版Tomcat
Netty是什么: 异步事件驱动框架,用于快速开发高i性能服务端和客户端 封装了JDK底层BIO和NIO模型,提供高度可用的API 自带编码解码器解决拆包粘包问题,用户只用关心业务逻辑 精心设计的Re ...
- Netty学习摘记 —— 再谈EventLoop 和线程模型
本文参考 本篇文章是对<Netty In Action>一书第七章"EventLoop和线程模型"的学习摘记,主要内容为线程模型的概述.事件循环的概念和实现.任务调度和 ...
- Netty 核心组件 Pipeline 源码分析(二)一个请求的 pipeline 之旅
目录大纲: 前言 针对 Netty 例子源码做了哪些修改? 看 pipeline 是如何将数据送到自定义 handler 的 看 pipeline 是如何将数据从自定义 handler 送出的 总结 ...
- [编织消息框架][netty源码分析]4 eventLoop 实现类NioEventLoop职责与实现
NioEventLoop 是jdk nio多路处理实现同修复jdk nio的bug 1.NioEventLoop继承SingleThreadEventLoop 重用单线程处理 2.NioEventLo ...
- [编织消息框架][netty源码分析]5 eventLoop 实现类NioEventLoopGroup职责与实现
分析NioEventLoopGroup最主有两个疑问 1.next work如何分配NioEventLoop 2.boss group 与child group 是如何协作运行的 从EventLoop ...
- Netty 核心组件笔记
Netty是一款高效的NIO框架和工具,基于JAVA NIO提供的API实现. 在JAVA NIO方面Selector给Reactor模式提供了基础,Netty结合Selector和Reactor模式 ...
- Netty源代码学习——EventLoopGroup原理:NioEventLoopGroup分析
类结构图: watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvd29ya2luZ19icmFpbg==/font/5a6L5L2T/fontsize/400/f ...
随机推荐
- Syclover 第十次极客大挑战web题题解
这次有空的时候报名参加了一下三叶草的招新比赛,比赛时间是一个月,题目都挺基础挺好玩的,在这里记一下自己的题解同时把自己没有做的题目也跟着writeup做一遍 第一题:cl4y:打比赛前先撸一只猫!: ...
- bert实践
github参考:https://github.com/wangjiwu/BERT-sentiment--classification 一.准备数据 bert官方与训练数据下载 自己的数据集,(训练集 ...
- 彻底搞懂js this指向问题
在这里必须要提一句的是,this指向是学习js必须要掌握的(必须),再开始之前先看底部的总结,然后回上面看例子便一目了然. 例子1: function a(){ var user = "Ta ...
- x++ 和 ++x的区别
很多编程语言都会有x++和++x的问题,两个到底是怎么回事? 一个先执行一个后执行的区别 var x = 0; console.log(x++);//0 遇到x++当前执行值不变 console.lo ...
- centos安装scrapy
安装scrapy centos 7 安装scrapy报错说找不到scrapy需要的Twisted13.0以上版本? Collecting Twisted>=13.1.0 (from Scrapy ...
- Day1 数据类型
整数 十六进制和八进制使用0作为前缀,如 0x12f , 010浮点数 可以用科学计数法来表示很大或者很小的浮点数,如 1.23x10^9 可以写作 1.23e9 或者12.3e8 ,0.000012 ...
- Cisco Packet Tracer NAT模拟实验
Cisco Packet Tracer NAT模拟实验 by: 铁乐猫 date: 2020-09-22 cisco packet tracer : 7.2.2 NAT简介 NAT允许将私有IP地址映 ...
- k8s ingress - traefik
前面提到过 k8s 的 ingress 有 ingress-nginx,traefik,haproxy 等多种.今天来实践一下 tarefik. 闲言少叙,直接上代码. # cat traefik.y ...
- uwsgi 的app变量名称必须为application
from myproject import app as application if __name__ == "__main__": application.run() 否则会提 ...
- NET 5 依赖注入多个服务实现类
依赖注入在 ASP.NET Core 中起中很重要的作用,也是一种高大上的编程思想,它的总体原则就是:俺要啥,你就给俺送啥过来. 服务类型的实例转由容器自动管理,无需我们在代码中显式处理. 因此,有了 ...