分享内容如下:

  1. NioEventLoopGroup初始化分析
  2. NioEventLoopGroup父子类分析
  3. parentGroup与childGroup区别

1.NioEventLoopGroup初始化分析

从接口类图上看 EventLoopGroup 继承了 线程池和定时线程池功能,判断EventLoopGroup具有线程池的复合功能。从命名猜测 EventLoopGroup 管理了一组 EventLoop

protected MultithreadEventExecutorGroup(int nThreads, Executor executor, Object... args) {

//.......

//executor默认初始化类型为ThreadPerTaskExecutor

if (executor == null) {

executor = new ThreadPerTaskExecutor(newDefaultThreadFactory());

}

//创建了length=8的EventExecutor组

children = new EventExecutor[nThreads];

for (int i = 0; i < nThreads; i ++) {

boolean success = false;

try {

// 返回NioEventLoop

//NioEventLoopGroup 覆盖了newChild方法

children[i] = newChild(executor, args);

success = true;

} catch (Exception e) {

}

}

}

ThreadPerTaskExecutor分析

if (executor == null) {

executor = new ThreadPerTaskExecutor(newDefaultThreadFactory());

}

//使用了新的ThreadFactory,为生成的线程增加线程名前缀。

线程名前缀规则: 类简名+“-”+ThreadFactory序号+“-”

如: nioEventLoopGroup-2-

后缀:从1开始每创建一次加入

完整线程名如下

nioEventLoopGroup-2-1

nioEventLoopGroup-2-2

nioEventLoopGroup的ThreadFactory序号是2

生成的线程 toString:Thread[nioEventLoopGroup-2-1,10,main]  其中nioEventLoopGroup-2-1是线程名,10是优先级策略,main是组名默认生成

因为io.netty.util.concurrent.GlobalEventExecutor 提前加载,其中字段调用了一次DefaultThreadFactory构造方法。

代码:private final ThreadFactory threadFactory = new DefaultThreadFactory(getClass());

public final class ThreadPerTaskExecutor implements Executor {

private final ThreadFactory threadFactory;

//threadFactory赋值

public ThreadPerTaskExecutor(ThreadFactory threadFactory) {

if (threadFactory == null) {

throw new NullPointerException("threadFactory");

}

this.threadFactory = threadFactory;

}

@Override

//使用threadFactory创建线程

public void execute(Runnable command) {

threadFactory.newThread(command).start(); //生成新线程,并以单线程执行 command

}

}

这里需要 注意 ThreadPerTaskExecutor.execute(Runnable command) 是以单线程运行的。NioEventLoop启动 调用了这个方法。

小结:ThreadPerTaskExecutor使用了新的ThreadFactory,为生成的线程增加线程名前缀。

实现了创建新线程,并以单线程执行 Runnable 的execute方法。

EventLoopGroup 中重要的两个方法,newChild()和next(),代码如下。

NioEventLoopGroup-newChild()

@Override

protected EventLoop newChild(Executor executor, Object... args) throws Exception {

return new NioEventLoop(this, executor, (SelectorProvider) args[0]);

}

}

newChild:创建NioEventLoop

NioEventLoopGroup只有这个一个覆盖方法。创建NioEventLoop

MultithreadEventExecutorGroup-next()

@Override

public EventExecutor next() {

return children[Math.abs(childIndex.getAndIncrement() % children.length)];

}

next:轮询获取从Reactor线程组的NioEventLoop

小结:NioEventLoopGroup初始化最主要的任务是创建了NioEventLoop数组。

2.NioEventLoopGroup父子类分析

主要的接口类图如下

EventExecutorGroup:next 获取EventExecutor, 线程任务执行, 定时任务

EventExecutor:多了newPromise,inEventLoop();

EventLoopGroup:只有EventLoop next();

EventLoop:只有以下3个方法

EventLoopGroup parent();//暂时不分析

EventLoop next();//看了其实现类 都是return this

ChannelHandlerInvoker asInvoker();//返回一个包装handler执行的invoker,默认使用

分析NioEventLoopGroup中的父子类

NioEventLoopGroup类图如下

AbstractEventExecutorGroup:next 获取EventExecutor未实现。线程任务执行, 定时任务都是 next().xxx()

MultithreadEventExecutorGroup:类注释的意思是多线程方式处理任务,从代码实现上来看,没有多线程的处理,主要功能是维护EventExecutor数组,实现了next()。

主要方法如下

protected MultithreadEventExecutorGroup(int nThreads, Executor executor, Object... args) {

//.......

children = new EventExecutor[nThreads];

for (int i = 0; i < nThreads; i ++) {

boolean success = false;

try {

//创建size()=nThreads的线程组

children[i] = newChild(executor, args);

success = true;

} catch (Exception e) {

} finally {

//......

}

}

//重要:实现了next获取EventExecutor

public EventExecutor next() {

return children[Math.abs(childIndex.getAndIncrement() % children.length)];

}

//由子类实现

protected abstract EventExecutor newChild(Executor executor, Object... args) throws Exception;

MultithreadEventLoopGroup:类注释无参照意义。主要功能是获取默认的线程数,/重写next返回类型为EventLoop

private static final int DEFAULT_EVENT_LOOP_THREADS;

static {

//获取默认的线程数

DEFAULT_EVENT_LOOP_THREADS = Math.max(1, SystemPropertyUtil.getInt(

"io.netty.eventLoopThreads", Runtime.getRuntime().availableProcessors() * 2));

}

//重写next返回类型为EventLoop

public EventLoop next() {

return (EventLoop) super.next();

}

newChild 还是没有实现

NioEventLoopGroup:

主要方法如下

//设置 希望child event loops 占用IO线程执行与执行任务的百分比。默认值是50, 此时I/O 和 non-I/O 将会试图占用相同的时间。

public void setIoRatio(int ioRatio) {

for (EventExecutor e: children()) {

((NioEventLoop) e).setIoRatio(ioRatio);

}

}

//替换原来的Selector,处理著名的epoll 100% bug,依赖NioEventLoop实现

public void rebuildSelectors() {

for (EventExecutor e: children()) {

((NioEventLoop) e).rebuildSelector();

}

}

//重写 newChild,创建NioEventLoop

protected EventLoop newChild(Executor executor, Object... args) throws Exception {

return new NioEventLoop(this, executor, (SelectorProvider) args[0]);

}

小结:NioEventLoopGroup主要功能是维护EventExecutor数组,实现了next(),暴露了一些线程,工具类方法, 都是依赖NioEventLoop实现。

3.parentGroup与childGroup区别

parentGroup是Reactor模式中主Reactor线程组,childGroup是从Reactor线程组。

怎么区分,当客户端发起连接时,服务需要获取相应的连接与之通讯,此时childGroup发挥作用。

这时会调用AbstractNioMessageChannel$NioMessageUnsafe.read() ,它理解 5.0.0版本parentGroup和childGroup的重要点

public void read() {

//...............................

try {

for (;;) {// 此处用到了循环,有可能 同时有2个以上的客户端发起连接

int localRead = doReadMessages(readBuf);代码A

if (localRead == 0) {

break;

}

if (localRead < 0) {

closed = true;

break;

}

if (readBuf.size() >= maxMessagesPerRead | !autoRead) {

break;

}

}

} catch (Throwable t) {

exception = t;

}

int size = readBuf.size();

for (int i = 0; i < size; i ++) {

pipeline.fireChannelRead(readBuf.get(i));代码B

}

readBuf.clear();

pipeline.fireChannelReadComplete();

//..............................................

}

代码A获取原生SocketChannel,使用childGroup中EventLoop 后创建了NioSocketChannel,使用。

代码B触发ChannelRead事件,最后执行了注册,启动了NioSocketChannel的EventLoop 线程。

这个方法中 获取并启动了 childGroup中的NioEventLoop

小结:server端在接受连接后创建了NioSocketChannel,注册在ChildGroup上,由此可推测,parentGroup负责接受客户端链接,childGroup负责IO操作。

总结:NioEventLoopGroup 管理了一组 NioEventLoop,parentGroup负责接受客户端链接,childGroup负责IO操作。

netty源码分析5-NioEventLoopGroup相关推荐

  1. Netty源码分析第1章(Netty启动流程)----第4节: 注册多路复用

    Netty源码分析第1章(Netty启动流程)---->第4节: 注册多路复用 Netty源码分析第一章:Netty启动流程   第四节:注册多路复用 回顾下以上的小节, 我们知道了channe ...

  2. 【Netty源码分析摘录】(八)新连接的接入

    文章目录 1.问题 2.检测新连接接入 3.创建客户端 channel 4. 绑定 NioEventLoop 4.1 register0 4.1.1 doRegister() 4.1.2 pipeli ...

  3. Netty源码分析第6章(解码器)----第4节: 分隔符解码器

    Netty源码分析第6章(解码器)---->第4节: 分隔符解码器 Netty源码分析第六章: 解码器 第四节: 分隔符解码器 基于分隔符解码器DelimiterBasedFrameDecode ...

  4. Netty源码分析第7章(编码器和写数据)----第2节: MessageToByteEncoder

    Netty源码分析第7章(编码器和写数据)---->第2节: MessageToByteEncoder Netty源码分析第七章: Netty源码分析 第二节: MessageToByteEnc ...

  5. Netty源码分析第5章(ByteBuf)----第5节: directArena分配缓冲区概述

    Netty源码分析第5章(ByteBuf)---->第5节: directArena分配缓冲区概述 Netty源码分析第五章: ByteBuf 第五节: directArena分配缓冲区概述 上 ...

  6. Netty源码分析系列之常用解码器(下)——LengthFieldBasedFrameDecoder

    扫描下方二维码或者微信搜索公众号菜鸟飞呀飞,即可关注微信公众号,Spring源码分析和Java并发编程文章. 前言 在上一篇文章中分析了三个比较简单的解码器,今天接着分析最后一个常用的解码器:Leng ...

  7. Netty源码分析(六)—Future和Promis分析

    Netty源码分析(六)-Future和Promis分析 Future用来在异步执行中获取提前执行的结果 个人主页:tuzhenyu's page 原文地址:Netty源码分析(六)-Future和P ...

  8. Netty源码分析系列之服务端Channel的端口绑定

    扫描下方二维码或者微信搜索公众号菜鸟飞呀飞,即可关注微信公众号,Spring源码分析和Java并发编程文章. 微信公众号 问题 本文内容是接着前两篇文章写的,有兴趣的朋友可以先去阅读下两篇文章: Ne ...

  9. netty源码分析系列——EventLoop

    2019独角兽企业重金招聘Python工程师标准>>> 前言 EventLoop也是netty作为一个事件驱动架构的网络框架的重要组成部分,netty主要通过它来实现异步编程,从前面 ...

  10. Netty 源码分析系列(十五)自定义解码器、编码器、编解码器

    前言 我们今天继续来分析 Netty 的编解码器,这次我们要自己动手实现自定义的编码器.解码器和编解码器. 自定义基于换行的解码器 LineBasedFrameDecoder 类 LineBasedF ...

最新文章

  1. Verilog testbench总结(二)
  2. Windows 窗体设计器中的设计时错误
  3. c++17进阶(3)-Boehm GC垃圾回收(1)
  4. 1109: 胥哥的DOTA-水题(直接做,时间也不超限)
  5. swagger api文档_带有Swagger的Spring Rest API –创建文档
  6. 前端学习(2854):简单秒杀系统学习之settimeout
  7. Spring简洁总结
  8. 结合内存分析java归并排序_排序算法之归并排序(Mergesort)解析
  9. (https)nginx - tomcat(http)
  10. Spring,FetchType.LAZY和FetchType.EAGER什么区别?
  11. 【SQL】日期型函数
  12. java面试基础_java面试之基础(总结)
  13. (一)Flask 学习 —— Hello World
  14. 桂林理工大学 大学语文题库2021年春季学期
  15. MATLAB必看书籍推荐
  16. STM32F103C8T6详细引脚表
  17. php 半角 全角空格,全角空格和半角空格
  18. Redis过期策略---实现原理
  19. 【网络】远程连接路由器
  20. java 7 反射_【7】java 反射详解

热门文章

  1. 从数据结构到python编程
  2. RK3288:linux系统中基于I2C的数字温度传感器TCN75A的驱动调试
  3. 算法ppt练习题(给黄成个大逼兜)
  4. (遇到问题)ubuntu遇到文件夹带锁如何去除,已解决
  5. Linux如何去掉文件夹的锁
  6. “青海年·醉海东”系列活动启幕 多民族“共烹”河湟文化年
  7. 321酷生活导航第一期:AIDN(js和flash类的小游戏)
  8. iOS_青花瓷Charles抓包
  9. 智能投影机android系统,投影仪内置安卓系统的好吗?当贝OS有多强?
  10. 郑商所比赛交易日志1