Netty源码分析---ThreadPerTaskExecutor与线程创建详解

【Netty源码系列(二)】解读EventLoopGroup 【Netty源码系列文章】 解读EventLoopGroup 阅读详情

相关文章链接

位运算详解

waken方法详解

ThreadPerTaskExecutor与线程创建详解

processSelectedKeys() vs runAllTasks()

NioServerSocketChannel-Unsafe初始化详解

NioEventLoop的run方法详解

NioEventLoopGroup深度解析

inEventLoop方法详解

executionMask详解

Netty源码分析–认真系列(一)

Netty源码分析–认真系列(二)

ThreadPerTaskExecutor 与线程创建详解

一、从 NioEventLoopGroup 初始化说起

我们在使用 Netty 的时候,通常会这样创建 NioEventLoopGroup:

EventLoopGroup bossGroup = new NioEventLoopGroup();
EventLoopGroup workerGroup = new NioEventLoopGroup();

在 NioEventLoopGroup 的初始化过程中,会经过一系列的构造方法调用,最终到达 MultithreadEventExecutorGroup 的构造方法。在这个构造方法中,有一段非常关键的代码:

// MultithreadEventExecutorGroup.java
protected MultithreadEventExecutorGroup(int nThreads, Executor executor,
                                        EventExecutorChooserFactory chooserFactory, 
                                        Object... args) {
    // 参数校验
    if (nThreads <= 0) {
        throw new IllegalArgumentException(
            String.format("nThreads: %d (expected: > 0)", nThreads));
    }

    // 重点:如果 executor 为 null,创建默认的 ThreadPerTaskExecutor
    if (executor == null) {
        executor = new ThreadPerTaskExecutor(newDefaultThreadFactory());
    }
    
    // ... 后续代码
}

这里的 if (executor == null) 判断非常重要,因为我们在创建 NioEventLoopGroup 的时候没有传入 Executor,所以这里会创建一个默认的 ThreadPerTaskExecutor。这个 ThreadPerTaskExecutor 就是负责为每个 NioEventLoop 创建线程的关键组件。

二、ThreadPerTaskExecutor 是什么

我们先来看 ThreadPerTaskExecutor 的源码:

// ThreadPerTaskExecutor.java
public final class ThreadPerTaskExecutor implements Executor {
    private final ThreadFactory threadFactory;

    public ThreadPerTaskExecutor(ThreadFactory threadFactory) {
        this.threadFactory = threadFactory;
    }

    @Override
    public void execute(Runnable command) {
        // 每次调用 execute,都会创建一个新线程并启动
        threadFactory.newThread(command).start();
    }
}

ThreadPerTaskExecutor 实现了 JDK 的 Executor 接口,但它和我们常用的 ThreadPoolExecutor 完全不同。ThreadPoolExecutor 是线程池,会维护一个线程池,任务提交后会被分配到池中的线程执行。而 ThreadPerTaskExecutor 每次调用 execute() 方法都会创建一个新线程。

这里有个关键点:ThreadPerTaskExecutor 不是用来执行普通任务的,它只是用来为每个 NioEventLoop 创建工作线程。每个 NioEventLoop 只会在启动的时候调用一次 executor.execute(),创建一个线程后就一直复用这个线程,不会再创建新线程了。所以不回造成资源的浪废

三、ThreadFactory 的创建过程

现在我们来看 ThreadPerTaskExecutor 的构造方法参数 threadFactory 是怎么来的。回到上面的代码:

if (executor == null) {
    executor = new ThreadPerTaskExecutor(newDefaultThreadFactory());
}

这里调用了 newDefaultThreadFactory() 方法,我们来看这个方法的实现:

// MultithreadEventExecutorGroup.java
protected ThreadFactory newDefaultThreadFactory() {
    return new DefaultThreadFactory(getClass());
}

这个方法很简单,就是创建了一个 DefaultThreadFactory 实例,传入的参数是当前类的 Class 对象。因为我们创建的是 NioEventLoopGroup,所以这里的 getClass() 返回的是 NioEventLoopGroup.class。

四、DefaultThreadFactory 的实现

现在我们来详细看看 DefaultThreadFactory 是如何实现的:

// DefaultThreadFactory.java
public class DefaultThreadFactory implements ThreadFactory {
    
    // 静态的 poolId 计数器,所有 DefaultThreadFactory 实例共享
    // 每创建一个 DefaultThreadFactory,poolId 就会递增
    private static final AtomicInteger poolId = new AtomicInteger();
    
    // 线程编号计数器,每个 DefaultThreadFactory 实例独有
    // 每创建一个线程,nextId 就会递增
    private final AtomicInteger nextId = new AtomicInteger();
    
    // 线程名前缀,例如:nioEventLoopGroup-2-
    private final String prefix;
    
    // 是否是守护线程
    private final boolean daemon;
    
    // 线程优先级
    private final int priority;
    
    // 线程组
    protected final ThreadGroup threadGroup;

    // 构造方法1:传入 Class 对象
    public DefaultThreadFactory(Class<?> poolType) {
        this(poolType, false, Thread.NORM_PRIORITY);
    }

    // 构造方法2:传入 Class 对象、是否守护线程、优先级
    public DefaultThreadFactory(Class<?> poolType, boolean daemon, int priority) {
        this(toPoolName(poolType), daemon, priority);
    }

    // 构造方法3:真正做事的构造方法
    public DefaultThreadFactory(String poolName, boolean daemon, int priority) {
        // 生成线程名前缀
        // poolId.incrementAndGet() 会让 poolId 递增并返回新值
        // 例如:nioEventLoopGroup-2-
        prefix = poolName + '-' + poolId.incrementAndGet() + '-';
        
        // 保存是否守护线程的标志,默认是 false(非守护线程)
        this.daemon = daemon;
        
        // 保存线程优先级,默认是 Thread.NORM_PRIORITY(5)
        this.priority = priority;
        
        // 获取线程组
        // 如果没有安全管理器,使用当前线程的线程组
        // 如果有安全管理器,使用安全管理器的线程组
        threadGroup = System.getSecurityManager() == null ?
                Thread.currentThread().getThreadGroup() :
                System.getSecurityManager().getThreadGroup();
    }

    // 将 Class 转换为线程池名称
    private static String toPoolName(Class<?> poolType) {
        // 获取类的简单名称,例如 NioEventLoopGroup
        String poolName = poolType.getSimpleName();
        
        // 将首字母转换为小写
        // 例如:NioEventLoopGroup -> nioEventLoopGroup
        return poolName.isEmpty() ? "unknown" : 
            Character.toLowerCase(poolName.charAt(0)) + poolName.substring(1);
    }

    @Override
    public Thread newThread(Runnable r) {
        // 创建新线程
        // threadGroup: 线程组
        // r: 要执行的任务(Runnable)
        // prefix + nextId.incrementAndGet(): 线程名,例如 nioEventLoopGroup-2-1
        // 0: 栈大小,0 表示使用默认值
        Thread t = new Thread(threadGroup, r, 
            prefix + nextId.incrementAndGet(), 0);
        
        // 设置是否为守护线程
        // 如果当前线程的守护状态和期望的不一致,就设置一下
        if (t.isDaemon() != daemon) {
            t.setDaemon(daemon);
        }
        
        // 设置线程优先级
        // 如果当前线程的优先级和期望的不一致,就设置一下
        if (t.getPriority() != priority) {
            t.setPriority(priority);
        }
        
        return t;
    }
}

五、线程名的生成规则

我们来详细说说线程名是怎么生成的。假设我们创建了两个 NioEventLoopGroup:

EventLoopGroup bossGroup = new NioEventLoopGroup(1);   // 1 个线程
EventLoopGroup workerGroup = new NioEventLoopGroup(4); // 4 个线程

第一步:生成 poolName

在 DefaultThreadFactory 的构造方法中,会调用 toPoolName(poolType) 方法:

private static String toPoolName(Class<?> poolType) {
    String poolName = poolType.getSimpleName();  // "NioEventLoopGroup"
    return Character.toLowerCase(poolName.charAt(0)) + poolName.substring(1);  // "nioEventLoopGroup"
}

所以 poolName 就是 "nioEventLoopGroup"。

第二步:生成 prefix

在 DefaultThreadFactory 的构造方法中,会生成 prefix:

prefix = poolName + '-' + poolId.incrementAndGet() + '-';

因为 poolId 是静态的,所有 DefaultThreadFactory 实例共享,所以:

  • 第一个 NioEventLoopGroup(bossGroup)创建时,poolId 从 0 递增到 1,prefix = "nioEventLoopGroup-1-"
  • 第二个 NioEventLoopGroup(workerGroup)创建时,poolId 从 1 递增到 2,prefix = "nioEventLoopGroup-2-"

第三步:生成线程名

当调用 newThread() 方法创建线程时,会生成线程名:

Thread t = new Thread(threadGroup, r, prefix + nextId.incrementAndGet(), 0);

因为 nextId 是实例变量,每个 DefaultThreadFactory 实例独有,所以:

  • bossGroup 的第 1 个线程:"nioEventLoopGroup-1-1"
  • workerGroup 的第 1 个线程:"nioEventLoopGroup-2-1"
  • workerGroup 的第 2 个线程:"nioEventLoopGroup-2-2"
  • workerGroup 的第 3 个线程:"nioEventLoopGroup-2-3"
  • workerGroup 的第 4 个线程:"nioEventLoopGroup-2-4"

六、线程创建的完整流程

现在我们把整个流程串起来,看看一个 NioEventLoop 的线程是如何创建的:

1. NioEventLoopGroup 初始化

EventLoopGroup workerGroup = new NioEventLoopGroup();

2. 创建 ThreadPerTaskExecutor

在 MultithreadEventExecutorGroup 的构造方法中:

if (executor == null) {
    // 调用 newDefaultThreadFactory() 创建 DefaultThreadFactory
    // 然后用 DefaultThreadFactory 创建 ThreadPerTaskExecutor
    executor = new ThreadPerTaskExecutor(newDefaultThreadFactory());
}

3. 创建 NioEventLoop

在 MultithreadEventExecutorGroup 的构造方法中,会循环创建 NioEventLoop:

for (int i = 0; i < nThreads; i ++) {
    // 调用 newChild() 方法创建 NioEventLoop
    // 把 executor 传进去
    children[i] = newChild(executor, args);
}

4. NioEventLoop 保存 executor

在 NioEventLoop 的构造方法中(实际上是在父类 SingleThreadEventExecutor 中):

protected SingleThreadEventExecutor(EventExecutorGroup parent, Executor executor, ...) {
    this.parent = parent;
    // 把 executor 保存起来,后面会用到
    this.executor = executor;
}

注意:这里只是保存了 executor,还没有创建线程。

5. 触发线程创建

当 Channel 注册到 NioEventLoop 时,会调用 eventLoop.execute(task):

// SingleThreadEventExecutor.java
public void execute(Runnable task) {
    boolean inEventLoop = inEventLoop();
    addTask(task);
    if (!inEventLoop) {
        // 如果当前线程不是 EventLoop 线程,就启动 EventLoop 线程
        startThread();
    }
}

6. 启动线程

// SingleThreadEventExecutor.java
private void startThread() {
    if (state == ST_NOT_STARTED) {
        if (STATE_UPDATER.compareAndSet(this, ST_NOT_STARTED, ST_STARTED)) {
            try {
                doStartThread();
            } catch (Throwable cause) {
                STATE_UPDATER.set(this, ST_NOT_STARTED);
            }
        }
    }
}

private void doStartThread() {
    // 调用 ThreadPerTaskExecutor 的 execute 方法
    executor.execute(new Runnable() {
        @Override
        public void run() {
            // 保存线程引用
            thread = Thread.currentThread();
            // 执行 NioEventLoop 的 run() 方法
            SingleThreadEventExecutor.this.run();
        }
    });
}

7. ThreadPerTaskExecutor 创建线程

// ThreadPerTaskExecutor.java
@Override
public void execute(Runnable command) {
    // 调用 DefaultThreadFactory 的 newThread() 方法创建线程
    // 然后调用 start() 启动线程
    threadFactory.newThread(command).start();
}

8. DefaultThreadFactory 创建线程

// DefaultThreadFactory.java
@Override
public Thread newThread(Runnable r) {
    // 创建新线程,线程名:nioEventLoopGroup-2-1
    Thread t = new Thread(threadGroup, r, 
        prefix + nextId.incrementAndGet(), 0);
    
    // 设置为非守护线程
    if (t.isDaemon() != daemon) {
        t.setDaemon(daemon);
    }
    
    // 设置线程优先级
    if (t.getPriority() != priority) {
        t.setPriority(priority);
    }
    
    return t;
}

9. 线程启动

调用 t.start() 后,线程启动,开始执行 Runnable 的 run() 方法,也就是 NioEventLoop 的 run() 方法。这个 run() 方法会一直循环,处理 I/O 事件和任务队列中的任务。

八、总结

整个线程创建的流程可以总结为:

  1. NioEventLoopGroup 初始化时,创建 ThreadPerTaskExecutor 和 DefaultThreadFactory
  2. 创建多个 NioEventLoop,每个 NioEventLoop 都持有 ThreadPerTaskExecutor
  3. 当 Channel 注册到 NioEventLoop 时,触发线程创建
  4. NioEventLoop 调用 executor.execute()
  5. ThreadPerTaskExecutor 调用 threadFactory.newThread() 创建线程
  6. DefaultThreadFactory 创建 Thread 对象,设置线程名、优先级等属性
  7. 调用 thread.start() 启动线程
  8. 线程执行 NioEventLoop 的 run() 方法,开始循环处理事件
2024最新实战:用1Panel面板+Docker快速部署Frps服务端(含Nginx配置模板) 本文详细介绍了2024年企业级内网穿透方案,通过1Panel面板和Docker技术快速部署Frps服务端,包含Nginx反向代理配置模板。从服务器选型、系统准备到安全加固,提供全栈实战指南,帮助企业和开发者高效实现内网穿透需求。 阅读详情

相关推荐

光耦继电器电路分析

光耦电路的分析笔记

MingYue_SSS的博客 6887

Netty源码分析---startThread方法详解

本文解析了Netty中startThread()方法的实现原理。该方法通过状态检查和CAS操作确保线程安全启动,使用ThreadPerTaskExecutor创建并启动新线程。关键点包括:1)状态检查避免重复启动;2)CAS操作保证原子性;3)异常处理恢复状态;4)通过ThreadFactory创建命名线程。该方法最终会执行EventLoop的run()方法进入事件循环。

java_rutu的博客 687

别再只改config了!YOLO/RT-DETR多通道输入实战:数据集结构、多卡训练与参数优先级避坑指南

本文详细解析了YOLO/RT-DETR模型在多通道输入(如8通道多光谱图像)中的实战应用,涵盖数据集结构优化、数据加载器改造、模型参数调优及多卡训练配置。针对常见的多通道输入报错问题,提供了系统的解决方案和性能优化技巧,帮助开发者高效实现非标准数据格式的适配与训练。

weixin_30955617的博客 397

Netty源码分析NioEventLoopGroup和NioEventLoop ——(一)

机缘巧合之下看了Netty的源码,但是这玩意对我来说使用的频率确实不多,为了加深自己的记忆,也为了以后可以更快的上手,打算写几篇博客从源码角度来梳理下netty的主线, 本篇也是第一篇。 在Netty中它的“线程池”和“线程”分别用NioEventLoopGroup和NioEventLoop来表示,通常我们用下面几行代码来配置服务端和客户端的线程池。 //client Bootstrap bootstrap = new Bootstrap(); NioEventLoopGroup grou.

start_mao的博客 406

最新版IAR9.40和注册工具

IAR最新版的IDE在编译速度和代码提示等各个方面上都有很大提升,软件这个东西果然还是越新越好。之前的时候,IAR v9系列网上很多人都说能用,但是又没有把 IAR v9系列的注册方法写的很清楚,导致我一直都用注册老版本v8的方法去注册v9。结果注册后都会提示。

xue_nuo的博客 4万+

双有源桥(DAB)进阶:EPS调制策略与Matlab/Simulink仿真实践

本文深入探讨了双有源桥(DAB)的扩展移相(EPS)调制策略及其在Matlab/Simulink中的仿真实践。通过分析EPS的两种黄金调制策略——回流功率消除和电流应力优化,结合实际工程案例,展示了如何提升DAB系统的效率和性能。文章还详细介绍了Simulink模型搭建要点和关键仿真结果,为工程师提供了实用的技术参考。

weixin_33734785的博客 484

Netty源码分析(二):NioEventLoop创建过程

文章目录NioEventLoopGroup的构造函数先来看ThreadPerTaskExecutornewChild()方法创建NioEventLoop创建线程选择器chooserFactory.newChooser() NioEventLoop创建 NioEventLoopGroup的构造函数 默认传入nThreads为0,一直跟踪构造函数,直到最高层 先来看ThreadPerTask...

博客 556

把数字化转型真正落到组织里:读懂 SAP 的 OCM 六维框架

摘要: SAP的变革管理框架(OCM)强调数字化转型不仅是技术任务,更需关注组织与人的适应性。OCM包含六大维度:变革战略(明确方向与风险)、变革领导力(统一关键管理者行动)、变革沟通(分层传递信息)、变革实现(细化岗位级影响)、变革赋能(按角色设计培训)和变革有效性(持续评估)。该框架贯穿项目全周期,尤其在云项目中,需从早期规划变革策略,避免后期高代价调整。OCM的核心是将系统设计转化为组织语言,确保业务真正采纳新方式运作。

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 1437

Netty源码分析 - NioEventLoopGroup

NioEventLoopGroup是处理netty连接和IO操作的NioEventLoop执行者组 对于服务端,netty会创建两个不同类型的组,一个成为bossGroup负责处理accept事件,一个为workerGroup负责处理read/write/connect事件。 EventLoopGroup bossGroup = new NioEventLoopGroup(1); EventLoopGroup workerGroup = new NioEventLoopGroup(); 服务端使用上

yangzsirr的博客 477

梯度提升决策树GBDT原理与代码实例讲解

梯度提升决策树GBDT原理与代码实例讲解 1.背景介绍 1.1 机器学习发展历程 机器学习是人工智能领域的一个重要分支,旨在使计算机具备学习和改进自身性能的能力。随着大数据时代的到来,海量的数据为机器学习算法提供了广阔的应用空间。在

AI天才研究院 1089

GEE案例教程:融合Sentinel-1 SAR数据、Sentinel-2光学影像和WorldPop人口数据,构建完整的洪水监测与影响评估工作流

本文介绍了一个专为巴基斯坦哈扎拉分区设计的洪水监测系统,该系统整合了Sentinel-1 SAR数据、Sentinel-2光学影像和WorldPop人口数据等多源遥感数据。系统通过VV极化SAR数据的水体提取算法(阈值-13dB)实现洪水范围监测,结合10米分辨率的光学影像进行可视化验证,并利用100米分辨率人口数据评估受灾人口。系统提供完整的技术实现,包括研究区加载、遥感数据处理、日期选择界面和洪水变化检测等功能模块,为灾害应急响应提供科学依据。

此星光明博客 191

Netty源码解析-EventLoop-DefaultEventLoop启动过程

Netty源码解析-EventLoop-DefaultEventLoop启动过程DefaultEventLoop继承关系DefaultEventLoop初始化DefaultEventLoop提交任务 Netty version : 4.1.53.Final 有任何错误或者建议可以留言交流,谢谢 DefaultEventLoop DefaultEventLoop是EventLoop的一个最简单实现,为方便更好理解后面NioEventLoop做准备。 继承关系 DefaultEventLoop初始化 从ne

acm160920007的博客 641

“守望先锋”网络同步分析

守望先锋”(Overwatch)是一款由暴雪娱乐开发的团队基础第一人称射击游戏(FPS),于2016年正式发布。游戏以其独特的角色设计、丰富的游戏模式和高度的团队合作性而受到广泛欢迎。类型:第一人称射击(FPS)/多人在线战斗竞技场(MOBA元素)平台玩家人数:每场比赛由两个六人队伍组成,共12名玩家。客户端/服务器模型:在这种模型中,客户端负责处理用户输入和表现逻辑,而服务器则负责游戏的核心逻辑和状态管理。客户端与服务器之间通过网络进行通信,确保游戏状态的一致性。强同步机制。

本博客聚焦游戏开发技巧、创业实战心得及大学热门课程干货。这里既有技术深度,也有思维广度,无论你是开发者、创业者还是高校学子,都能在这里找到适合自己的成长之路! 429

Netty(八)源码解析 之 NioEventLoopGroup和NioEventLoop源码分析、NioEventLoop绑定线程的流程分析

NioEventLoop源码 1. NioEventLoopGroup的构造分析 EventLoopGroup parentGroup = new NioEventLoopGroup(); EventLoopGroup childGroup = new NioEventLoopGroup(); 我们先从NioEventLoopGroup开始,NioEventLoopGroup根据名字就能知道里面肯定包含了很多NioEventLoop 先看下NioEventLoop继承体系: 关键点:NioEventLo

语雀同名:犬豪 yuque.com/qhao 2071

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

Netty NioEventLoop 创建过程源码分析

原文链接:https://wangwei.one/posts/net... 前面 ,我们分析了Netty中的Channel组件,本篇我们来介绍一下与Channel关联的另一个核心的组件 —— EventLoop。 Netty版本:4.1.30 概述 EventLoop定义了Netty的核心抽象,用于处理网络连接生命周期中所有发生的事件。...

weixin_34221276的博客 89

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

Netty源码分析第2章(NioEventLoop)---->第1节: NioEventLoopGroup之创建线程执行器

Netty源码分析第2章(NioEventLoop)---->第1节: NioEventLoopGroup之创建线程执行器 Netty源码分析第二章: NioEventLoop 概述: 通过上一章的学习, 我们了解了Server启动的大致流程, 有很多组件与模块并没有细讲, 从这个章开始, 我们开始详细剖析...

weixin_30341735的博客 378

浅谈Netty中的NioEventLoop

NioEventLoop创建 步骤 new NioEventLoopGroup() 线程组,默认2*cpu new ThreadPerTaskExecutor() 线程创建器 每次执行任务都会创建一个线程实体 for(){newChild()} 构造NioEventLoop 保存线程执行器ThreadPerTaskExecutor 创建一个MpscQueue 创建一个selector ...

weixin_33862514的博客 231

写自己的netty源码分析--NioEventLoop

目录 绪论 步骤一:NioEventLoop创建 new ThreadPerTaskExecutor()[线程创建器] 每次执行任务时都会创建一个线程实体(FastThreadLocalThread--封装的一个线程) 识别nioEventLoop-1-xx for(){newChild()} [构造NioEventLoop] 创建一个selector 保存线程执行器Threa...

qq_40722284的博客 294

吃透Netty源码系列一之NioEventLoopGroup

Netty源码深度解析系列一前言Netty的Reactor模式 前言 netty更新的是快,最新发布版本已经是4.1.45.Final了,以前有学过netty,觉得学的还不够深入,这次打算从源码级别去更加深入的理解内部机制。我不想介绍太多关于netty是什么,怎么用,我更想介绍一下原理,这样才能更好的去使用它,扩展它,完善它。我打算从常用的一些类开始介绍,比如NioEventLoopGroup S...

王伟王胖胖的博客 5662

netty源码分析(二)Netty对Executor的实现机制源码分析

上一节说到NioEventLoopGroup 的初始化,到了他的父类MultithreadEventExecutorGroup的构造器: protected MultithreadEventExecutorGroup(int nThreads, Executor executor, EventExecuto

wzq6578702的专栏 1434

netty源码分析5-NioEventLoopGroup

分享内容如下: NioEventLoopGroup初始化分析 NioEventLoopGroup父子类分析 parentGroup与childGroup区别 1.NioEventLoopGroup初始化分析 从接口类图上看 EventLoopGroup 继承了 线程池和定时线程池功能,判断EventLoopGroup具有线程池的复合功能。从命名猜测 EventLoopGroup 管理了一组...

chenchangqun11的专栏 565

第二节 netty源码分析之NioEventLoopGroup的构造函数分析

一、概述 上一节中,讲了netty的基本应用。这一节主要是根据上一节的应用代码一行行的进行netty的源码分析。上一节的应用代码的main函数里面的第一行是new NioEventLoopGroup(1),下面就分析一下NioEventLoopGroup 的构造方法。 二、NioEventLoopGroup 从类的名字翻译出来 Nio事件轮训组。讲道理的话,它跟线程组是一个意思,都是有一组线程在做同样的申请,就是轮训Channel的IO事件。 先看NioEventLoopGroup 的构造方法。 publi

Resee_Z的博客 425

Netty源码分析(一)之NioEventLoopGroup

netty版本 NioEventLoopGroup NioEventLoopGroup调用分析 DefaultEventExecutorChooserFactory MultithreadEventLoopGroup核心代码分析 ThreadPerTaskExecutor 总结 netty版本 使用的netty版本是io.netty:netty-all:4.1.29...

jannal专栏 290

netty源码分析之揭开reactor线程的面纱(一)

netty最核心的就是reactor线程,对应项目中使用广泛的NioEventLoop,那么NioEventLoop里面到底在干些什么事?netty是如何保证事件循环的高效轮询和任务的及时执行?又是如何来优雅地fix掉jdk的nio bug?带着这些疑问,本篇文章将庖丁解牛,带你逐步了解netty reactor线程的真相[源码基于4.1.6.Final] reactor 线程的启动 NioE...

爱传文档的专栏 183

InnoDB 内存结构总览:Change Buffer、AHI 与 Log Buffer

本文系统梳理InnoDB内存结构中的ChangeBuffer、Adaptive Hash Index(AHI)与LogBuffer。ChangeBuffer缓存二级索引页不在内存时的变更,减少随机IO,仅在页加载时合并;聚簇索引修改立即执行,因数据本身不可延后。AHI基于高频等值查询自动构建哈希索引,加速定位,仅支持等值操作。LogBuffer为redo log内存缓冲,配合磁盘日志实现崩溃恢复。三者均服务于性能优化,其中ChangeBuffer与AHI共享BufferPool空间,而LogBuffer独立

bksczm的博客 298
上一篇: Netty源码分析---processSelectedKeys() vs runAllTasks()
下一篇: Netty源码分析---waken方法详解
不早睡不改名@
博客等级 码龄5年 536粉丝 306原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值