你的位置:首页 > ASP.net教程

[ASP.net教程]Reactor 模式的简单实现


Reactor 模式简单实现

 

在网上有部分文章在描述Netty时,会提到Reactor。这个Reactor到底是什么呢?为了搞清楚Reactor到底是什么鬼,我写了一个简单的Demo,来帮助大家理解他。

 

网上是这么描述Reactor的:

The Reactor design pattern handles service requests that are delivered concurrently to an application by one or more clients.

Each service in an application may consist of serveral methods and is represented by a separate event handler that is responsible for dispatching service-specific requests.

Dispatching of event handlers is performed by an initiation dispatcher, which manages the registered event handlers. Demultiplexing of service requests is performed by a synchronous event demultiplexer.

    大致意思是:Reactor是用于处理多个客户端的请求的设计模式。应用程序提供的每一种服务都可能包括多个方法,并且有必要为这每一个服务分配独立的请求处理器(也可以说是 event handler)。对于Event handler的调度是有Dispatcher来执行的,这个Dispatcher可以管理event handler的注册工作。而分离器Demultiplexer则将一个服务分成了多份。这段话看起来还是不那么容易理解的。

    我对这段话的理解是:应用程序提供多种服务,而每一种服务都会分为多步骤(或者多类别)进行。这里将每一步都作为一个事件,那么每一步的处理就认为是一个event handler。Dispatcher管理这多个步骤的处理器,也即dispatcher管理着多个Event Handler。而将一个服务处理分为多步骤(多个类别)的处理的工作则是有分离器来完成。

 

 

 

 

从这个类图上看,主要有四个角色:

·Handle:事件源。

    ·EventHandler:事件处理器

    ·Dispatcher:调度器。使用Demultiplexer选出可以执行处理的EventHandler,然后执行对EventHandler的调度。

    ·Demultiplexer:同步的事件分离器。

   

 

从类图上看:Dispatcher中有一个Selector和一个EventHandler集合(可以是List,也可以是Map,具体怎么实现根据实际需求)。Regist_handler、remove_handler用于管理EventHandler。

Handle_events用于启动调度,这个方法的实现通常是:使用分离器选择出可以调度的Event,然后对它们进行调度。

 

下面就是对Reactor模式的简单实现:

 

package com.fjn.jdk.nio.reactor.standard;import java.util.ArrayList;import java.util.Date;import java.util.List;import java.util.Map;import java.util.concurrent.BlockingQueue;import java.util.concurrent.ConcurrentHashMap;import java.util.concurrent.LinkedBlockingQueue;public class StandardReactor {}class EventDispatcher {  Map<EventType, EventHandler> eventHandlerMap = new ConcurrentHashMap<EventType, EventHandler>();  Demultiplexer selector;  EventDispatcher(Demultiplexer selector) {    this.selector = selector;  }  public void registEventHandler(EventType eventType, EventHandler eventHandler) {    eventHandlerMap.put(eventType, eventHandler);  }  public void removeEventHandler(EventType eventType) {    eventHandlerMap.remove(eventType);  }  public void handleEvents() {    dispatch();  }  private void dispatch() {    while (true) {      List<Event> events = selector.select();      for (Event event : events) {        EventHandler eventHandler = eventHandlerMap.get(event.type);        eventHandler.handle(event);      }    }  }}class Demultiplexer {  private BlockingQueue<Event> eventQueue = new LinkedBlockingQueue<Event>();  private Object lock = new Object();  List<Event> select() {    return select(0);  }  List<Event> select(long timeout) {    if (timeout > 0) {      if (eventQueue.isEmpty()) {        synchronized (lock) {          if (eventQueue.isEmpty()) {            try {              lock.wait(timeout);            } catch (InterruptedException e) {              // ignore it            }          }        }      }    }    List<Event> events = new ArrayList<Event>();    eventQueue.drainTo(events);    return events;  }  public void addEvent(Event e) {    boolean success = eventQueue.offer(e);    if (success) {      synchronized (lock) {        lock.notify();      }    }  }}class Source {  private Date date = new Date();  private String id = date.toString() + "_" + System.identityHashCode(date);  @Override  public String toString() {    return id;  }}enum EventType {  ACCEPT, READ, WRITE, TIMEOUT;}class Event {  public EventType type;  public Source source;}abstract class EventHandler {  Source source;  public abstract void handle(Event event);  public Source getSource() {    return source;  }}class AcceptEventHandler extends EventHandler {  private Demultiplexer selector;  public AcceptEventHandler(Demultiplexer selector) {    this.selector = selector;  }  @Override  public void handle(Event event) {    if (event.type == EventType.ACCEPT) {      Event readEvent = new Event();      readEvent.source = event.source;      readEvent.type = EventType.READ;      selector.addEvent(readEvent);    }  }}class ReadEventHandler extends EventHandler {  // private Pipeline pipeline;    @Override  public void handle(Event event) {    // create channel with a pipeline    // register the channel to this event dispatcher or a child event dispatcher         // handle event use the pipeline :    // step 1: read to a frame buffer    // step 2: use frame decoder to decode buffer as a message (maybe a business object)    // step 3: handle the message or submit the message to business thread pool    // step 4: register a message event      }  } class WriteEventHandler extends EventHandler {    @Override  public void handle(Event event) {    // step 1: encode a message to byte[]    // step 2: submit a write task to IOWorker thread pool   }  }//-------------------------------分割线--------------------------//class Acceptor implements Runnable {  private int port; // server socket port  private Demultiplexer selector;  // 代表 serversocket  private BlockingQueue<Source> sourceQueue = new LinkedBlockingQueue<Source>();  Acceptor(Demultiplexer selector, int port) {    this.selector = selector;    this.port = port;  }  public void aNewConnection(Source source) {    sourceQueue.offer(source);  }  public int getPort() {    return this.port;  }  public void run() {    while (true) {      Source source = null;      try {        // 相当于 serversocket.accept()        source = sourceQueue.take();      } catch (InterruptedException e) {        // ignore it;      }      if (source != null) {        Event acceptEvent = new Event();        acceptEvent.source = source;        acceptEvent.type = EventType.ACCEPT;        selector.addEvent(acceptEvent);      }    }  }}class Server {  Demultiplexer selector = new Demultiplexer();  EventDispatcher eventLooper = new EventDispatcher(selector);  Acceptor acceptor;  Server(int port) {    acceptor = new Acceptor(selector, port);  }  public void start() {    eventLooper.registEventHandler(EventType.ACCEPT, new AcceptEventHandler(selector));    new Thread(acceptor, "Acceptor-" + acceptor.getPort()).start();    eventLooper.handleEvents();  }}