一、什么是线程模型
简单地说,线程模型指定了操作系统、编程语言、框架或者应用程序的上下文中的线程管理的关键方面。
在早期的 Java 语言中,我们使用多线程处理的主要方式无非是按需创建和启动新的 Thread 来执行并发的任务单元,这种在高负载下表现得很原始。Java 5 随后引入了 Executor API,其线程池通过缓存和重用Thread 极大地提高了性能。
基本的线程池化模式可以描述为:
- 从池的空闲线程列表中选择一个 Thread,并且指派它去运行一个已提交的任务(一个Runnable 的实现);
- 当任务完成时,将该 Thread 返回给该列表,使其可被重用。
就像这样,线程再步骤3和4之间无限循环:
这种模式有个缺陷就是:
虽然池化和重用线程相对于简单地为每个任务都创建和销毁线程是一种进步,但是它并不能消除由上下文切换所带来的开销。这种开销将随着线程数量的增加很快变得明显,并且在高负载下愈演愈烈。此外,仅仅由于应用程序的整体复杂性或者并发需求,在项目的生命周期内也可能会出现其他和线程相关的问题。
二、EventLoop 接口
首先介绍一个术语: 运行任务来处理在连接的生命周期内发生的事件是任何网络框架的基本功能。与之相应的编程上的构造通常被称为事件循环。
下面我们展示了一个事件循环的基本思想,其中每个任务都是一个 Runnable 的实例。
while (!terminated) {
//阻塞,直到有事件已经就绪可被运行
List<Runnable> readyEvents = blockUntilEventsReady();
//遍历处理事件
for (Runnable ev: readyEvents) {
ev.run();
}
}
在Netty中 使用了 interface io.netty.channel.EventLoop来搭配事件循环。它采用了两个基本的 API:并发和网络编程。
- 首先,io.netty.util.concurrent 包构建在 JDK 的 java.util.concurrent 包上,用来提供线程执行器。
- 其次,io.netty.channel 包中的类,为了与 Channel 的事件进行交互,扩展了这些接口/类。
它的的类层次结构就像下面一样:
看起来比较复杂&