EventLoop绑定到Channel的过程详解

Netty hello world 入门源码分析 第一节简单提了什么是网络编程,Netty 做了什么,Netty 都有哪些功能组件。这一节就具体进入 Netty 的世界,我们从用 Netty 的功能实现基本的网络通信开始分析 各个组件的使用。 1. 一个简单的发送接收消息的例子 话不多说,先来实现一个发送接收消息的例子。本实例基于 SpringBoot 工程搭建。 项目类文件如下: 客户端和服务端的主要代码分为3个部分:启动器,ChannelInitializer,eventHandler。 相关代码已经上传 GitHub,请参阅:点我 (๑¯ ³ ¯๑ 阅读详情

EventLoop 绑定到 Channel 的过程详解

问题:channel.eventLoop() 返回的 EventLoop 是什么时候初始化的?

在 Bootstrap.doConnect() 方法中有这样一行代码:

channel.eventLoop().execute(new Runnable() {
    @Override
    public void run() {
        channel.connect(remoteAddress, connectPromise);
    }
});

这里的 channel.eventLoop() 返回的 EventLoop 实例是在 register 过程中 绑定到 Channel 的。


一、EventLoop 绑定的完整流程

1.1 时间线

Bootstrap.connect()
  ↓
doResolveAndConnect()
  ↓
initAndRegister()  ← 【这里完成 EventLoop 的绑定】
  ├─→ channelFactory.newChannel()  // 创建 Channel
  ├─→ init(channel)                // 初始化 Channel
  └─→ group().register(channel)    // 注册 Channel,绑定 EventLoop
       ↓
doResolveAndConnect0()
  ↓
doConnect()
  ↓
channel.eventLoop().execute()  ← 【这里使用已绑定的 EventLoop】

1.2 关键点

  • EventLoop 绑定发生在 register 阶段
  • 在 doConnect() 调用时,EventLoop 已经绑定好了
  • 一个 Channel 一旦绑定了 EventLoop,就不会再改变

二、详细代码追踪

2.1 入口:initAndRegister()

// AbstractBootstrap
final ChannelFuture initAndRegister() {
    Channel channel = null;
    try {
        // 1. 创建 Channel(此时 eventLoop 还是 null)
        channel = channelFactory.newChannel();
        
        // 2. 初始化 Channel(配置 pipeline 等)
        init(channel);
    } catch (Throwable t) {
        // ...
    }

    // 3. 【关键】注册 Channel 到 EventLoopGroup,这里会绑定 EventLoop
    ChannelFuture regFuture = config().group().register(channel);
    
    if (regFuture.cause() != null) {
        if (channel.isRegistered()) {
            channel.close();
        } else {
            channel.unsafe().closeForcibly();
        }
    }
    
    return regFuture;
}

此时 Channel 的状态:

  • channel.eventLoop = null(还未绑定)

2.2 选择 EventLoop:group().register(channel)

// MultithreadEventLoopGroup
@Override
public ChannelFuture register(Channel channel) {
    // 【关键】从 EventLoopGroup 中选择一个 EventLoop
    // next() 方法会使用 EventExecutorChooser 选择策略(轮询或幂次方优化)
    return next().register(channel);
}

next() 方法的作用:

  • 从 EventLoopGroup 中选择一个 EventLoop
  • 使用轮询策略(如果线程数是 2 的幂次方,使用位运算优化)
  • 返回选中的 EventLoop 实例

示例:

// 假设创建了 4 个 EventLoop
EventLoopGroup group = new NioEventLoopGroup(4);

// 第一次调用 next(),返回 eventLoop[0]
// 第二次调用 next(),返回 eventLoop[1]
// 第三次调用 next(),返回 eventLoop[2]
// 第四次调用 next(),返回 eventLoop[3]
// 第五次调用 next(),返回 eventLoop[0](循环)

2.3 EventLoop 注册 Channel:eventLoop.register(channel)

// SingleThreadEventLoop
@Override
public ChannelFuture register(Channel channel) {
    return register(new DefaultChannelPromise(channel, this));
}

@Override
public ChannelFuture register(final ChannelPromise promise) {
    ObjectUtil.checkNotNull(promise, "promise");
    
    // 【关键】调用 Channel 的 unsafe.register()
    // 注意:这里把 this(当前 EventLoop)传进去了
    promise.channel().unsafe().register(this, promise);
    
    return promise;
}

关键点:

  • 这里的 this 就是从 EventLoopGroup 中选出来的 EventLoop 实例
  • 将这个 EventLoop 传递给 Channel 的 unsafe.register() 方法

2.4 绑定 EventLoop:unsafe.register(eventLoop, promise)

// AbstractChannel.AbstractUnsafe
@Override
public final void register(EventLoop eventLoop, final ChannelPromise promise) {
    // ...省略部分代码
    
    // 【核心】将 EventLoop 绑定到 Channel
    // 从此以后,这个 Channel 就属于这个 EventLoop 了
    AbstractChannel.this.eventLoop = eventLoop;

    // 判断当前线程是否是 EventLoop 的线程
    if (eventLoop.inEventLoop()) {
        // 如果是,直接执行 register0
        register0(promise);
    } else {
        // 如果不是,提交任务到 EventLoop 的任务队列
        try {
            eventLoop.execute(new Runnable() {
                @Override
                public void run() {
                    register0(promise);
                }
            });
        } catch (Throwable t) {
            // ...
        }
    }
}

关键代码:

AbstractChannel.this.eventLoop = eventLoop;

这一行代码完成了 EventLoop 的绑定!

此时 Channel 的状态:

  • channel.eventLoop = 从 EventLoopGroup 中选出的 EventLoop 实例
  • 这个绑定关系是永久的,不会改变

2.5 后续使用:channel.eventLoop()

// AbstractChannel
@Override
public EventLoop eventLoop() {
    EventLoop eventLoop = this.eventLoop;
    if (eventLoop == null) {
        throw new IllegalStateException("channel not registered to an event loop");
    }
    return eventLoop;
}

作用:

  • 返回在 register 阶段绑定的 EventLoop 实例
  • 如果还未绑定,抛出异常

三、完整流程图

用户代码: bootstrap.connect("localhost", 8080)
         ↓
Bootstrap.doResolveAndConnect()
         ↓
Bootstrap.initAndRegister()
         ↓
channelFactory.newChannel()
[创建 NioSocketChannel]
[此时 channel.eventLoop = null]
         ↓
init(channel)
[初始化 Pipeline]
         ↓
config().group().register(channel)
         ↓
MultithreadEventLoopGroup.next()
[从 EventLoopGroup 中选择一个 EventLoop]
[假设选中了 eventLoop[2]]
         ↓
eventLoop[2].register(channel)
         ↓
SingleThreadEventLoop.register(promise)
         ↓
channel.unsafe().register(eventLoop[2], promise)
         ↓
AbstractUnsafe.register(eventLoop, promise)
         ↓
【核心】AbstractChannel.this.eventLoop = eventLoop
[绑定完成!channel.eventLoop = eventLoop[2]]
         ↓
eventLoop.execute(register0 任务)
[提交 register0 任务到 eventLoop[2] 的任务队列]
         ↓
[register 完成,返回到 doResolveAndConnect()]
         ↓
doResolveAndConnect0()
         ↓
doConnect()
         ↓
channel.eventLoop().execute(connect 任务)
[使用已绑定的 eventLoop[2]]
[提交 connect 任务到 eventLoop[2] 的任务队列]

四、关键问题解答

Q1:EventLoop 是什么时候创建的?

A:EventLoop 在创建 EventLoopGroup 时就已经创建好了。

// 用户代码
EventLoopGroup workerGroup = new NioEventLoopGroup(4);

// 这一行代码会创建 4 个 NioEventLoop 实例
// 每个 NioEventLoop 内部包含:
// - 一个 Selector
// - 一个任务队列(taskQueue)
// - 一个定时任务队列(scheduledTaskQueue)
// - 但此时还没有创建 Thread(线程是懒加载的)

Q2:EventLoop 的线程是什么时候创建的?

A:线程是在第一次提交任务时创建的(懒加载)。

// 在 AbstractUnsafe.register() 中
eventLoop.execute(new Runnable() {
    @Override
    public void run() {
        register0(promise);
    }
});

// 这是第一次向 EventLoop 提交任务
// 此时会触发线程的创建(在 SingleThreadEventExecutor.execute() 中)

Q3:一个 Channel 可以绑定多个 EventLoop 吗?

A:不可以。一个 Channel 只能绑定一个 EventLoop,而且一旦绑定就不会改变。

原因:

  • 保证线程安全:所有 IO 操作都在同一个线程中执行
  • 保证事件顺序:事件按提交顺序执行
  • 简化编程模型:无需考虑并发问题

Q4:一个 EventLoop 可以绑定多个 Channel 吗?

A:可以。一个 EventLoop 可以管理多个 Channel。

示例:

EventLoopGroup (4 个 EventLoop)
├─ EventLoop[0]
│   ├─ Channel A
│   ├─ Channel B
│   └─ Channel C
├─ EventLoop[1]
│   ├─ Channel D
│   └─ Channel E
├─ EventLoop[2]
│   └─ Channel F
└─ EventLoop[3]
    ├─ Channel G
    ├─ Channel H
    └─ Channel I

Q5:如何选择 EventLoop?

A:使用 EventExecutorChooser 选择策略。

// MultithreadEventLoopGroup 构造函数中
chooser = chooserFactory.newChooser(children);

// 两种策略:
// 1. PowerOfTwoEventExecutorChooser(线程数是 2 的幂次方)
//    使用位运算:index = idx.getAndIncrement() & (executors.length - 1)
//
// 2. GenericEventExecutorChooser(线程数不是 2 的幂次方)
//    使用取模:index = Math.abs(idx.getAndIncrement() % executors.length)

五、代码示例

5.1 验证 EventLoop 绑定

public class EventLoopBindingDemo {
    public static void main(String[] args) throws Exception {
        EventLoopGroup group = new NioEventLoopGroup(4);
        
        Bootstrap bootstrap = new Bootstrap();
        bootstrap.group(group)
                .channel(NioSocketChannel.class)
                .handler(new ChannelInitializer<SocketChannel>() {
                    @Override
                    protected void initChannel(SocketChannel ch) {
                        // 在这里可以获取到绑定的 EventLoop
                        EventLoop eventLoop = ch.eventLoop();
                        System.out.println("Channel 绑定的 EventLoop: " + eventLoop);
                        System.out.println("EventLoop 的线程: " + eventLoop.inEventLoop());
                    }
                });
        
        // 连接多次,观察 EventLoop 的分配
        for (int i = 0; i < 10; i++) {
            ChannelFuture future = bootstrap.connect("localhost", 8080);
            future.addListener(f -> {
                if (f.isSuccess()) {
                    Channel channel = ((ChannelFuture) f).channel();
                    System.out.println("连接 " + i + " 使用的 EventLoop: " + channel.eventLoop());
                }
            });
        }
        
        Thread.sleep(5000);
        group.shutdownGracefully();
    }
}

输出示例:

连接 0 使用的 EventLoop: NioEventLoop@1234 (thread: nioEventLoopGroup-2-1)
连接 1 使用的 EventLoop: NioEventLoop@5678 (thread: nioEventLoopGroup-2-2)
连接 2 使用的 EventLoop: NioEventLoop@9abc (thread: nioEventLoopGroup-2-3)
连接 3 使用的 EventLoop: NioEventLoop@def0 (thread: nioEventLoopGroup-2-4)
连接 4 使用的 EventLoop: NioEventLoop@1234 (thread: nioEventLoopGroup-2-1)
...

可以看到,EventLoop 是轮询分配的。


六、时序图

用户线程                EventLoopGroup           EventLoop[2]              Channel
   |                         |                        |                       |
   |--connect()------------->|                        |                       |
   |                         |                        |                       |
   |--initAndRegister()----->|                        |                       |
   |                         |                        |                       |
   |                         |--newChannel()--------->|                       |
   |                         |                        |                       |
   |                         |<-----------------------|                       |
   |                         |      (channel)         |                       |
   |                         |                        |                       |
   |                         |--next()--------------->|                       |
   |                         |   (选择 EventLoop[2])  |                       |
   |                         |                        |                       |
   |                         |<-----------------------|                       |
   |                         |   (eventLoop[2])       |                       |
   |                         |                        |                       |
   |                         |--register(channel)---->|                       |
   |                         |                        |                       |
   |                         |                        |--unsafe.register()-->|
   |                         |                        |   (eventLoop[2])     |
   |                         |                        |                       |
   |                         |                        |                  【绑定】
   |                         |                        |          channel.eventLoop = eventLoop[2]
   |                         |                        |                       |
   |                         |                        |<----------------------|
   |                         |                        |                       |
   |<--regFuture-------------|                        |                       |
   |                         |                        |                       |
   |--doConnect()----------->|                        |                       |
   |                         |                        |                       |
   |                         |                        |<--eventLoop()---------|
   |                         |                        |   (返回 eventLoop[2]) |
   |                         |                        |                       |
   |                         |                        |<--execute(task)-------|
   |                         |                        |   (提交 connect 任务) |
   |                         |                        |                       |

七、总结

7.1 EventLoop 绑定的关键点

  1. 绑定时机:在 register 阶段,具体在 AbstractUnsafe.register() 方法中
  2. 绑定代码:AbstractChannel.this.eventLoop = eventLoop
  3. 选择策略:从 EventLoopGroup 中轮询选择一个 EventLoop
  4. 绑定关系:一个 Channel 只能绑定一个 EventLoop,且永久不变
  5. 使用时机:在 doConnect() 等方法中通过 channel.eventLoop() 获取

7.2 为什么要绑定 EventLoop?

  1. 线程安全:所有 IO 操作都在同一个线程中执行,无需加锁
  2. 事件顺序:保证事件按提交顺序执行
  3. 性能优化:避免线程切换和上下文切换
  4. 简化编程:用户无需考虑并发问题

7.3 EventLoop 的生命周期

创建 EventLoopGroup
  ↓
创建多个 EventLoop(但还没有线程)
  ↓
Channel 注册时,选择一个 EventLoop 并绑定
  ↓
第一次提交任务时,创建线程
  ↓
线程启动,进入 run() 循环
  ↓
处理 IO 事件和任务队列
  ↓
EventLoopGroup 关闭时,线程退出
从频谱分析到硬件加速:用ZYNQ-7020+FFT IP核实现实时信号处理的完整方案 本文详细介绍了如何利用ZYNQ-7020和FFT IP核实现实时信号处理的完整方案,涵盖系统架构设计、硬件加速实现及性能优化。通过异构计算架构,该方案将1024点FFT处理延迟压缩至28μs,显著提升工业自动化和无线通信等领域的实时频谱分析效率。 阅读详情

相关推荐

大数据工程中的多模态数据处理技术

模态”(Modality)指的是数据的表现形式文本(Text):新闻、评论、文案等;图像(Image):照片、截图、医学影像等;音频(Audio):语音、音乐、环境声音等;视频(Video):短视频、监控视频、电影等(本质是图像+音频的组合);数值/结构化数据(Numerical/Structured):用户年龄、商品价格、传感器数据等;时间序列(Time Series):股票价格、物流轨迹、心率数据等。多模态数据(Multimodal Data)是指包含两种或以上模态的数据集。

AI云原生与云计算技术学院 1276

IDEA 启动报错:java.lang.IllegalStateException: failed to create a child event loop 问题解决

遇到的问题 昨天电脑自动更新了,今天死活启动不了项目,看到idea的提示是: idea日志如下 根据提示说 查看idea的启动日志: 2018-11-20 17:35:42,010 [ 46737] INFO - plication.impl.ApplicationImpl - 118 application components initialized in 29017...

Soinice的博客 1万+

车道线检测1.0(Python+Opencv基础版)

车道线检测是指在道路上自动检测和识别车道线的过程。车道线是道路上的标记,用于指示车辆行驶的方向和位置。 通过对车道线进行检测和识别,自动驾驶和智能驾驶系统可以实现车辆的自动导航、车道保持、车道偏离警告等功能。

Dream_orz的博客 4265

深入解析java.lang.IllegalStateException异常

是Java中的一个非受检异常,它表示在不适当的时间或状态下调用方法。日志记录工具:如Log4j、Logback等,可以记录异常信息和错误日志,方便排查和分析问题。断言工具:如Assert类,可以在程序中添加断言语句,用于验证代码中的假设条件是否满足,帮助我们在开发和测试阶段快速发现问题。异常处理框架:如Spring框架中的异常处理机制,可以统一处理应用程序中的异常,提供统一的异常处理逻辑和错误信息返回。异常是程序中常见的错误和异常情况,合理处理异常对于保证程序的正确性和稳定性非常重要。

博客 4万+

opencv去除印章痕迹

今天看到一个很有意思的程序,就是去除票据上的红色印章,觉得很有意思,就把它抄过来记录一下,同时自己也开了一下脑洞。 原来的程序来自:https://www.cnblogs.com/skyfsm/p/7638301.html 可以看到图像效果很不错,下面是源码实现: #include &lt;iostream&gt; #include &lt;opencv2/imgproc/imgpro...

zeng_haoyu的博客 7961

【网络安全】SSRF漏洞讲解

SSRF漏洞讲解一、初识SSRF漏洞1.定义2.产生原理3.会导致的危害4.常见产生SSRF的地方5.常见缺失函数二、SSRF漏洞利用1.函数(1) file_get_contents(2)fsockopen()(3) curl_exec()2.协议(1)file协议(2)http协议(3)dict协议(4)gopher协议三、绕过1.绕过方式(1)检查IP是否为内网IP(2)Host获取与DNS绕过(3)通过各种协议(4)利用URL解析器滥用问题四、修复修复方案五、小结 一、初识SSRF漏洞 1.定义

你在看屏幕的同时,屏幕也在注视着你 3181

亲测有效,已解决java.lang.IllegalStateException异常的正确解决方法,嘿嘿嘿

出现 IllegalStateException 的原因可能有很多,但通常涉及以下几种情况: 对象状态不正确:例如,你可能尝试在一个没有初始化的对象上调用方法。 线程安全问题:多线程环境下,如果没有正确的同步,对象的状态可能会被破坏。 生命周期问题:在对象的生命周期中的某个不合适的时刻执行了某个操作。

PythonAigc的博客 1万+

小秋SLAM入门实战ubuntu所有文章汇总

ubuntu 终端如何停止快速打印的输出以及恢复命令 ubuntu 终端如何快速打开当前路径下的图形化窗口界面? killall -9用途用法 ps -xu | grep这个命令的用途 linux 下 top命令显示的是内存是堆内存吗? zip分割和合并 关闭除当前 GNOME 终端窗口以外的所有其他 GNOME 终端窗口 如何在安装系统后设置短密码 【如何使用getrusage获取消耗的CPU时间和进程使用的最大物理内存】 【webots安装使用教程】 Linux系统下查看当前运行的进程和线程的几种方法

小秋 AI SLAM 入门实战教程 1406

java.lang.IllegalStateException异常产生的原因及解决办法

(32806) (3) 问题描述: 错误类型大致为以下几种: java.lang.IllegalStateException:Cannot forward a response that is already committed IllegalStateException:response already commited IllegalStateExcept...

culous的博客 1万+

“华为杯“第十四届中国研究生数学建模竞赛-E题:多波次导弹发射中的规划问题(续)(附MATLAB代码实现)

将最长暴露时间的发射装置按照“优先隐蔽于转载地”,即增加该种发射装置的隐蔽时长,从而达到缩短最长暴露时间的目的。8.2 模型建立。

getusushu的博客 299

Python 爬虫实战:爬虫与 ECharts 结合 —— 前端可视化展示

本文介绍了爬虫技术与ECharts可视化结合的完整实现流程。首先使用Python爬取京东商品数据(价格、评价数等),通过BeautifulSoup解析和pandas处理转换为JSON格式。然后构建前端页面,利用ECharts实现价格分布柱状图、价格-评价数散点图和店铺占比饼图三种可视化效果。文章详细解析了爬虫数据提取、格式转换和前端图表配置等关键技术点,并提供了完整的代码示例。最后提出了基于API接口、数据库存储等扩展方向,为数据采集到可视化展示提供了完整的解决方案。

2503_91057718的博客 633

Netty服务端启动源码分析(三十一)

在服务器启动的常规代码里,首先是实例化 NioEventLoopGroup 和 ServerBootstrap,然 后是各种配置。各种配置基本上就是简单的 set。 比较特别的是 channel()方法,通过查看代码我们发现, 我们传入的是一个 Class 类型 的变量,Netty 将通过反射产生 Channel 的实例。 bind()方法 所以,关键代码就落在了 bind()方法上。这个方法实际调用的是 AbstractBootstrap 的 doBind()方法 ...

nandao158的博客 490

RK3399外设驱动之MIPI

RK3399外设驱动之MIPI 文章目录RK3399外设驱动之MIPIMIPI命令解析入口代码mipi显示配置实例rk3399mipi驱动rk mipi驱动注册过程rk32_mipi_dsi.c解析 内核版本 Linux4.4 平台 rk3399 作者 nineyole MIPI命令解析入口代码 MIPI的入口代码如下:kernel\drivers\video\rockchip\screen\lcd_mipi.c static int __init rk_mipi_screen_in

学无止境 2229

netty服务端启动流程总结

参考资料 NioEventLoopGroup源码分析 netty服务端启动流程源码分析 服务端启动做了哪些事情 //创建EventLoopGroup,初始化所有的EventLoop,初始化线程工具 EventLoopGroup bossEventLoopGroup = new NioEventLoopGroup(2); executor = new ThreadPerTaskExecutor(newDefaultThreadFactory()); //创建channel,初始化channel的pipel

weixin_38312719的博客 327

lwip-2.0.3

lwip是瑞典计算机科学院(SICS)的Adam Dunkels 开发的一个小型开源的TCP/IP协议栈。实现的重点是在保持TCP协议主要功能的基础上减少对RAM 的占用。

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

【Netty源码解析】启动流程全解析:ServerBootstrap如何绑定端口并启动

这个启动流程体现了Netty精良的设计和严谨的工程实践,为高性能网络通信奠定了坚实的基础。时,Netty内部究竟发生了什么?

持续输出Java相关知识 1010

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

【Netty】二.Channel与EventLoop深度解析

本文深入剖析了Netty中Channel与EventLoop的核心机制。Channel作为网络连接的抽象,具有完整的生命周期(创建、注册、激活、非激活、注销),每个状态变化都会触发相应事件。EventLoop是单线程事件循环执行器,负责处理I/O事件、执行任务和定时任务。关键点在于:1)Channel与EventLoop绑定后关系终身不变;2)所有Channel操作都在同一EventLoop线程执行,确保线程安全;3)通过inEventLoop()方法判断当前线程环境,正确处理任务调度。文章还对比了NIO与

hrh的博客 699

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

Channel、EventLoop、ChannelFuture

Channel、EventLoop(Group) 和ChannelFuture Channel—Socket; ChannelFuture—异步通知。 EventLoop—控制、多线程处理、并发; 关系图: 关系说明 一个EventLoopGroup 包含一个或者多个EventLoop; 一个EventLoop 在它的生命周期内只和一个Thread 绑定; 所有由EventLo...

JinXYan的博客 921

Netty核心机制:EventLoop与Channel的绑定过程深度解析

在高并发网络编程中,Reactor模型是常见的基础架构,Netty作为高性能网络框架,其线程模型设计直接影响系统吞吐。理解EventLoop与Channel的绑定关系是掌握Netty的关键。绑定过程涉及JDK Selector注册、线程亲缘性等原理,通过register调用链将Channel注册到EventLoop持有的Selector上,实现无锁串行处理。这种设计保证了单个Channel的操作线程封闭,避免并发冲突,但也要求Handler不得阻塞EventLoop,否则会拖累同线程上的其他连接。实际排障中

weixin_33290540的博客 315

Netty之EventLoop,EventLoopGroup,Channel

文章目录Netty之EventLoop,EventLoopGroup,Channel Netty之EventLoop,EventLoopGroup,Channel 一個EventLoopGroup當中會包含一個或多個EventLoop. 一個EventLoop在它的整個生命週期當中都只會與唯一一個Thread進行綁定. 所有由EventLoop所處理的各種I/O事件都將在它所關聯的那個Thre...

superbeyone 617

netty-02-EventLoop和channel相关

netty组件-EventLoopGroup和channel

ycmy2017的博客 728

Netty学习(二) EventLoop和Channel

EventLoop 本质是一个单线程执行器(同时维护了一个 Selector),里面有 run 方法处理 Channel 上源源不断的 io 事件。它的继承关系比较复杂。

2402_82958989的博客 854

Netty实战——Channel、EventLoop和ChannelFuture详解

Netty可以说是有Channel、EventLoop、ChannelFuture聚合起来的一个网络抽象代表 Channel——Socket; EventLoop——控制流、多线程处理、并发 ChannelFuture——异步通知 Channel接口 基本的I/O操作(bing()、connect()、read()、和write())依赖于底层网络传输所提供的原始。在基于Java的网络编程...

H_crab的博客 398

Netty源码分析——EventLoop于Channel的注册详解,以及其两者的关联关系

一个EventLoopGroup中会包含一个或者多个EventLoop 一个EventLoop在它的完整生命周期中只会与一个Thread进行绑定,该Thread在EventLoop初始化的时候被EventLoop作为属性持有 所有由EventLoop处理的各种I/O事件都会在其关联的Thread上执行(所以用时很长的业务逻辑请异步处理!其次,在执行的时候,会判断是否是当前的线程执行的任务,如果不是,则将该任务放入该EventLoop的执行器中执行,最终达到还是同一个线程执行的目录,所以是线程安全的)

保暖透气大裤衩LeoLee的博客 1612

Channel ChannelPipeline EventLoop

channel是通讯的载体,对应通讯的一端,在BIO中对应Socket,Nio中 对应SocketChannel, Netty中对应NioSocketChannel,ServerSocket同理channelHandler是通道的处理器,一个channel往往有多个handlerchannelpipeline是handler的容器,装载并管理handler的顺序(本质是双向链表)

qq_48704877的博客 642

Netty EventLoop与Channel绑定机制详解:从register到线程模型全链路

Netty作为高性能网络框架,其核心线程模型基于Reactor模式,其中EventLoop与Channel的绑定关系是理解整个IO模型的基础。这种绑定不仅意味着Channel的IO事件由唯一线程驱动,还决定了外部线程操作需通过任务队列转交,从而保证线程封闭与无锁并发。从Channel创建到首次register,再到bind与事件轮询,Netty通过AbstractChannel.register、Unsafe.register0等机制,将逻辑绑定与底层Selector注册分层实现。理解这一过程,有助于掌握异

weixin_30444111的博客 91

Netty是如何实现线程和Channel唯一绑定的

netty的线程模型对一个channel来说是单线程的,也就是说这个channel的所有读写事件都是同一个线程执行的,避免了多线程产生的并发问题.而一个eventloop是可以被多个channel绑定的,那么每次服务器连接一个channel之时,netty时如何知道使用哪个线程的呢? 本文描述背景假设对netty的使用比较熟悉,例如 ChannelContext,ChannelPipeline,...

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

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值