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 ...
随机推荐
- Raft概述
Raft 1. 概述 Raft是一种一致性(共识)算法,相比Paxos,Raft更容易理解和实现,它将分布式一致性问题分解成多个子问题,Leader选举(Leader election).日志复制(L ...
- 【题解】折纸 origami [SCOI2007] [P4468] [Bzoj1074]
[题解]折纸 origami [SCOI2007] [P4468] [Bzoj1074] 传送门:折纸 \(\text{origami [SCOI2007] [P4468]}\) \(\text{[B ...
- 《深入理解计算机系统》实验三 —— Buf Lab
这是CSAPP的第三个实验,主要让我们熟悉GDB的使用,理解程序栈帧的结构和缓冲区溢出的原理. 实验目的 本实验的目的在于加深对IA-32函数调用规则和栈结构的具体理解.实验的主要内容是对一个可执 ...
- STL——容器(Set & multiset)的删除 erase
set.clear(); //清除所有元素 set.erase(pos); //删除pos迭代器所指的元素,返回下一个元素的迭代器. set.erase(beg,end ...
- 安卓实用工具箱v4.3几百种小功能
款多功能实用工具箱.提供了从日常.图片.查询.设备.辅助.提取.优惠券.趣味游戏等多方面的功能,操作简单,即点即用,避免您下载超多应用的难题,且应用体积轻巧,界面简洁.已去除广告! 下载地址:http ...
- Java中四舍五入
1.Math中四舍五入的方法 Math.ceil(double a)向上舍入,将数值向上舍入为最为接近的整数,返回值是double类型 Math.floor(double a)向下舍入,将数值向下舍入 ...
- oracle 11g修改归档日志目录及大小
1.查看当前归档日志目录 SQL> show parameter recovery NAME TYPE VALUE ------------------------------------ -- ...
- 解决因缺少驱动程序,导致“未在本地计算机上注册microsoft.ace.12.0”异常
写了一个winform程序,功能是选择一个excel表格,把里面的内容写进sqlite数据库中,在本地测试没问题,但是在其他电脑上就会报错"未在本地计算机上注册microsoft.ace.1 ...
- 02-flask-路由基础
代码 from flask import Flask # 创建Flask对象 app = Flask(__name__) # 定义路由 @app.route('/') def index(): # 函 ...
- 仵航说 Vue用replace修改数组中对象的键值或者字段名 仵老大
仵航说 Vue用replace修改数组中对象的键值或者字段名 仵老大 1.介绍 先看图 今天在项目中遇到了一个问题,例如我现在需要传一些数据到后端,数组例如是 let arr = [ {" ...