线程模型指定了操作系统,编程语言,框架,应用程序的上下文的线程管理的关键方面
我们说下Netty的线程模型,为了简化应用程序代码,提高性能和维护性的线程模型
原本的Java线程从单线程模型到引入了线程池来进行优化
利用缓存和重用Thread提高了性能
但是这个模型并不能消除上下文切换带来的开销
所以Netty利用EventLoop来进一步简化
EventLoop是一个接口
事件循环本质上可以认为是处理轮训处理Runnable
EventLoop主要涉及的包有两个,一个是并发,一个是网络编程
concurrent和channel两个包中的接口
类的层次如下
一个EventLoop由一个不会改变的Thread驱动,任务直接提交给EventLoop来调度执行
Netty4中,所有的IO操作和事件都交由固定的Thread去处理,这些事件流经安装了一个或者多个的ChannelHandler的ChannelPipeline
关于Netty的任务调度
比如我们需要定时发送一个消息给远程节点
原本JDK中的定时方式利用Timer,后来利用scheduledExecutorService
利用调度命令在指定延迟后运行
这种API直截了当,但是高负载下有性能的负担
对于EvenLoop实现任务调度解决了这个问题
代码基本如下
经过60秒后,Runnable分配给Channel的EventLoop执行,如果需要周期性执行,可以把schedule方法换为scheduleAtFixedRate()
这也是由于EventLoop扩展了ScheduleExecutorService接口,方便我们调用
如果需要取消,则可以利用提交执行返回的ScheduleFuture
Netty的线程管理
对于一个事件的执行,需要确定是否分配给当前的Channel是在EventLoop的哪一个线程
如果这个线程是支撑EventLoop的线程,会被直接执行,不然会加入内部队列执行
EventLoop / 线程的分配
用于Channel的IO和事件的EventLoop包含在EvetnLoopGroup中
不同的Group中的Loop分配方式不尽相同
我们显示了一个EventLoopGroup,具有3个固定大小的EventLoop,
EventLoopGroup为每个Channel分配一个EventLoop
一般使用循环来进行均衡的分布
对于Netty的OIO的实现,则略有不同
每一个Channel都被分配给一个EventLoop
每一个Channel都只被一个Thread处理,这也是OIO的实现必要