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