Netty 系列目录 (https://www.cnblogs.com/binarylei/p/10117436.html)
在讲解 Reactor 线程模型之前, 我们需要先对基本并发编程模型: 串行工作模型, 并发工作模型进行讲解.
串行工作者模型和并行工作者模型关注的是将任务划分为 2 个阶段: 一是任务的接受阶段; 二是任务的处理阶段. 而 Reactor 线程模型关注的是上述第二个阶段: 任务在处理的过程中, 继续划分为多个步骤进行处理.
一, 串行模型
我们以一个典型的任务处理流程, 来说明为什么要将任务的接受流程与处理流程划分开来
在这个例子中, 一个 Worker 线程来处理用户提交的任务, 任务的处理步骤粗略的分为: 接受任务和处理任务两个阶段. 当 Worker 接受到一个任务之后, 就立刻进行处理, 也就是说任务接受和任务处理是在同一个 Worker 线程中进行的, 没有进行区分. 这样做存在一个很大的问题是, 必须要等待某个 Task 处理完成之后, 才能接受处理下一个 Task.
而通常情况下, 任务的处理过程会比任务的接受流程慢得多. 例如在处理任务的时候, 我们可能会需要访问远程数据库, 这属于一种网络 IO. 通常情况下 IO 操作是比较耗时的, 这直接影响了下一个任务的接受, 而且通常在 IO 操作的时候, CPU 是比较空闲的, 白白浪费了资源.
因此我们可以考虑将任务的接受与处理分为两个线程进行处理, 一个只负责接受任务, 一个只负责处理任务.
这就演化出了第一个线程模型: 串行工作者模型. 如下所示:
在这种情况下, 接受任务的线程称之为 Accept Thread, 其将接受到的任务放到一个任务队列中, 因此能立即返回接受下一个任务. 而 Worker 线程不断的从这个队列中取出任务进行异步执行.
目前这种情况存在一个很大的问题, 在于任务处理的太慢, 导致队列里积压的任务数量越来愈大, 任务不能得到及时的执行. 所以我们可以用多个 Worker Thread 来处理任务. 这就是串行工作者模型的并发版本 - 并行工作者模型.
二, 并行模型
在并行工作者模型中, 有一个 Accpet Thread, 多个 Worker Thread, 因为 Worker Thread 的功能都相同, 所以我们通常会将其划分到一个组中(Worker Thread Group).
在具体实现上, 并行工作者线程模型有两种设计方式, 以下分别进行介绍.
2.1 基于公共任务队列
并行工作者线程模型设计方式一: 基于公共任务队列
accept Thread 将接受到的任务放到任务队列中, Worker Thread group 中的多个 Worker Thread 并行的从公共的队列中拉取任务进行处理.
熟悉 java 线程池 的用户可能已经发现, 可以用 ThreadPoolExecutor 来实现右半部分的功能, 因为 ThreadPoolExecutor 就是多个线程从一个公共的任务队列中拉取任务进行执行. 通过在 main 线程中接受任务, 将任务提交到线程池中, 即可以完成上述线程模型.
2.2 每个 Worker Thread 维护自己的任务队列
在第一种方式中, 由于多个 Worker 线程同时从一个公共的任务队列中拉取任务进行处理, 因此必须要进行加锁, 因而影响了效率. 因此又有了下面一种设计方式: Reactor Thread 直接将任务转发给各个 Worker Thread, 每个 Worker Thread 内部维护一个队列来处理, 如下图
这种方式的设计, 避免的锁竞争, 因为每个 Worker Thread 都从各自的队列中取出任务进行执行. 实际上, Netty 的实现中, 就是为每个 Worker Thread 维护了一个队列.
需要注意的是: 由于现在是 Accpet Thread 直接给过个 Worker Thread 转发任务, 任务分配的平均的责任就落到了 Reactor Thread 的身上.
每天用心记录一点点. 内容也许不重要, 但习惯很重要!
来源: http://www.bubuko.com/infodetail-2883611.html