通过前两节我们已经知道了NIO的核心组件以及为什么要有NIO,虽然在Java中没有真的IO多路复用模型,但是Reactor就是NIO实现多路复用的一种模式。

Reactor是什么

Reactor设计模式是一种事件处理模式,用于处理通过一个或多个输入同时交付给服务处理程序的服务请求。然后,服务处理程序对传入的请求进行多路分解,并将它们同步分发到关联的请求处理程序。

Java 复用java包 java io复用_Java 复用java包

从上述表述中我们大致可以总结出:

基于事件驱动

可以处理一个或多个输入源

通过ServiceHandler同时将输入事件采用多路复用分发给相应的RequestHandler(多个)处理

对应我们的NIO中的实现:

同步的等待多个事件源(Event)到达(采用select()实现)

将事件多路分解以及分配相应的事件服务进行处理,这个分派采用server集中处理(Dispatch)

分解的事件以及对应的事件服务应用从分派服务中分离出去(RequestHandler)

Reactor结构

Java 复用java包 java io复用_多路_02

上述Reactor模型主要涉及的类有:

InitiationDispatcher:EventHandler的容器,用来注册、移除EventHandler等;另外,它作为Reactor模式的入口调用SynchronousEventDemultiplexer的select方法以阻塞等待事件的返回,当阻塞事件返回时,将事件发生的Handle分发到相应的EventHandler处理。

EvenHandler:定义了事件处理的方法。

Handle:即操作系统中的句柄,是对资源在操作系统层面上的一种抽象,它可以是打开的文件、一个连接Socket等。

SynchronousEventDemultiplexer:使用一个事件循环,以阻止所有的资源。当可以启动一个同步操作上的资源不会阻塞,多路分解器发送资源到分发器

Reactor时序图

Java 复用java包 java io复用_多路_03

初始化InitiationDispatcher,并初始化一个Handler到EventHandler的Map

注册EventHandler到InitiationDispatcher,每个EventHandler包含Handler的引用,从而建立Handler到EventHandler的映射

调用InitiationDispatcher的handle_events()方法启动EventLoop,在EventLoop中调用select()方法(SynchronousEventDemultiplexer)阻塞等待Event发生

当某个或某些Handler的Event发生以后,select()方法返回,InitiationDispatcher根据返回的Hanler找到注册的EventHandler,并回调该EventHandler的handler_event方法

在EventHandler的handler_event()方法中还可以向InitiationDispatcher中注册新的EventHandler,比如对AcceptorEventHandler来说,当有新的client连接时,它会产生新的EventHandler以处理新的连接,并注册到InitiationDispatcher中。

Reactor

Reactor单线程模型

Java 复用java包 java io复用_java nio io复用_04

最基本的单线程Reactor模型,Reactor负责多路分离套接字(阻塞并且当事件触发时进行分发),当有新连接触发到CONNECT事件后,交由Accptor处理,有IO读写事件交由Handler处理。

Accceptor负责获取与客户端建立的SocketChannel,绑定对应的EventHandler,当该SocketChannel上有事件发生时就可以获取到对应的EventHandler并进行处理。

单Reactor多线程模型

Java 复用java包 java io复用_多路_05

相对于单Reactor模型,我们在获取到IO事件以后可以交由线程池处理,可以减少Reactor线程的消耗,Reactor从而更加专注的关注于事件的分发。

多Reactor多线程模型

Java 复用java包 java io复用_单线程_06

mainReactor负责监听ServerSocket,用来处理新连接的建立,通常单线程就可以处理,将建立的SocketChannel指定注册给subReactor。

subReactor(它的个数一般是和CPU个数等同)维护自己的selector,基于mainReactor注册的socketChannel多路分离IO读写事件,读写网络数据,对业务处理的功能,将其扔给worker线程池来完成。

Reactor实现