Netty学习--EventLoop和线程模型

EventLoop 接口
EventLoop 的类层次结构

在这个模型中,一个EventLoop 将由一个永远都不会改变的Thread 驱动,同时任务(Runnable 或者Callable)可以直接提交给EventLoop 实现,以立即执行或者调度执行。根据配置和可用核心的不同,可能会创建多个EventLoop 实例用以优化资源的使用,并且单个EventLoop 可能会被指派用于服务多个Channel。

简单理解:一个EventLoop相当于一个循环,并有一条线程管理(Thread),当EventLoop添加或减少,线程也跟着改变.

  • Netty 4 中的I/O 和事件处理
    所有的I/O操作和事件都由已经被分配给了EventLoop的那个Thread来处理.
  • Netty 3 中的I/O 操作
    所有的出站(下游)事件都由调用线程处理,其可能是I/O 线程也可能是别的线程。
    问题一:多个出站事件同意调用一个ChannelHandle,因此需要在ChannelHandler 中对出站事件进行仔细的同步.
    问题二:当Channel.write()方法导致异常时,需要生成并触发一个exceptionCaught 事件。但是在Netty 3 的模型中,由于这是一个入站事件,需要在调用线程中执行代码,然后将事件移交给I/O 线程去执行,然而这将带来额外的上下文切换。
任务调度
  • 使用EventLoop 调度任务
Channel ch = ...
ScheduledFuture future = ch.eventLoop().schedule( // 调度任务在从现在开始的60 秒之后执行
new Runnable() {
    @Override
    public void run() {
        System.out.println("60 seconds later");
    }
}, 60, TimeUnit.SECONDS);
实现细节
  • 线程管理
EventLoop 的执行逻辑

永远不要将一个长时间运行的任务放入到执行队列中,因为它将阻塞需要在同一线程上执行的任何其他任务。如果必须要进行阻塞调用或者执行长时间运行的任务,我们建议使用一个专门的EventExecutor。
理解:一般EventLoop利用inEventLoop(Thread)绑定一条线程,如果需要多线程处理,则使用EventExecutor.

  • EventLoop/线程的分配
    1.异步传输
用于非阻塞传输(如NIO 和AIO)的EventLoop 分配方式

在当前实现中,使用顺序循环(round-robin)的方式进行分配以获取一个均衡的分布,并且相同的EventLoop可能会被分配给多个Channel。
对于所有相关联的Channel 来说,ThreadLocal 都将是一样的。(同一个线程)

2.阻塞传输

阻塞传输(如OIO)的EventLoop 分配方式

你可能感兴趣的:(Netty学习--EventLoop和线程模型)