netty实战笔记 第七章 EventLoop和线程模型

7.1 线程模型概述

java5 随后引入了Executor API, 其线程池通过缓存和重用Thread极大的提高了性能。
基本的线程池话模型描述为:
1.从池的空闲线程列表中选择一个Thread,并且指派它去运行一个已提交的任务(一个Runnable的实现)
2.当任务完成的时候,将该Thread返回给该列表,使其可被重用。

线程频繁的切换带来的是上下文切换的开销。随着线程数量的增多变得极其明显。

7.2 EventLoop接口

运行任务来处理在连接的生命周期内发生的事件是任何网络矿建的基本功能。对应的编程构造称之为事件循环(io.netty.channel.EventLoop).

EventLoop是协同设计的一部分。它采用了两个基本的API: 并发和网络编程。io.netty.util.concurrent包构建在jdk的java.util.concurrent包之上.用来提供线程执行器. io.nett.channel包中的类,为了与Channel的时间进行交互,扩展了这些接口和类。在这里插入图片描述
在这个模型中,一个EventLoop将由一个永远都不变的Thread驱动,同时任务(Runnable或者Callable)可以直接提交给EventLoop实现,以立即执行或者调度执行。根据机器配置和可用核心的不同,可能会创建多个EventLoop实例用以优化资源的使用。并且单个EventLoop可能会被指派用于服务多个Channel。
Netty的EventLoop在继承了ScheduledExecutorService的同时,只定义了一个方法parent().用于返回当前EventLoop实现的实例所属的EventLoopGroup的引用。

7.2.1 Netty4中的IO和事件处理

在Netty4中,所有的IO操作和事件都由已经被分配给了EventLoop的那个Thread来处理。

7.3 任务调度

7.3.1 JDK的任务调度

jdk1.5之前,任务调度建立在java.util.Timer类之上. 使用了后台Thread,并且具有与标准线程相同的限制. 随后,提供了java.util.concurrent包,其定义了ScheduledExecutorService。
详见java.util.concurrent.Executors类的工厂方法。

7.3.2 使用EventLoop调度任务

Channel ch = ..
Future f = ch.eventLoop().schedule(new Runnable(..),60,TimeUnit.SECONDS);
f.cancel(false);

60秒后,Runnable实例将有Channel的EventLoop执行。如果重复执行,调用scheduleAtFixedRate()方法。

7.4 实现细节

7.4.1 线程管理

Netty线程模型的卓越性能取决于对于当前执行的Thread的身份的确定.也就是说,确定它是否是分配给当前Channel以及它的EventLoop的那一个线程。

如果(当前)调用线程正是支撑EventLoop 的线程,那么所提交的代码块将会被(直接)执行。否则,EventLoop 将调度该任务以便稍后执行,并将它放入到内部队列中。当EventLoop下次处理它的事件时,它会执行队列中的那些任务/事件。这也就解释了任何的Thread 是如何与Channel 直接交互而无需在ChannelHandler 中进行额外同步的。

注意,每个EventLoop 都有它自已的任务队列,独立于任何其他的EventLoop。图7-3展示了EventLoop 用于调度任务的执行逻辑。这是Netty 线程模型的关键组成部分。
在这里插入图片描述

7.4.2 EventLoop 线程的分配

服务于Channel的IO和事件的EventLoop包含在EventLoopGroup中。根据不同的传输实现,EventLoop的创建和分配方式也不同。

  • 1.异步传输
    异步传输实现只使用了少量的EventLoop(以及和它们相关联的Thread),而且在当前的线程模型中,它们可能会被多个Channel 所共享。这使得可以通过尽可能少量的Thread 来支撑大量的Channel,而不是每个Channel 分配一个Thread
    在这里插入图片描述
    如上图, EventLoopGroup 负责为每个新创建的Channel 分配一个EventLoop。在当前实现中,使用顺序循环(round-robin)的方式进行分配以获取一个均衡的分布,并且相同的EventLoop可能会被分配给多个Channel。
    一旦一个Channel 被分配给一个EventLoop,它将在它的整个生命周期中都使用这个
    EventLoop

    另外,需要注意的是,EventLoop 的分配方式对ThreadLocal 的使用的影响。因为一个EventLoop 通常会被用于支撑多个Channel,所以对于所有相关联的Channel 来说,ThreadLocal 都将是一样的。这使得它对于实现状态追踪等功能来说是个糟糕的选择。然而,在一些无状态的上下文中,它仍然可以被用于在多个Channel 之间共享一些重度的或者代价昂贵的对象,甚至是事件。

  • 2.阻塞传输
    在这里插入图片描述
    每个channel都会被分配给一个EventLoop.每个Channel的IO事件都只会被一个Thread(用以支撑Channel的EventLoop的那个Thread)处理。

最后

如果你觉得写的还不错,就关注下公众号呗,关注后,有点小礼物回赠给你。
你可以获得5000+电子书,java,springCloud,adroid,python等各种视频教程,IT类经典书籍,各种软件的安装及破解教程。
希望一块学习,一块进步!
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

方_小_白

谢谢金主子,记得关注方家小白哦

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值