当前位置 博文首页 > weixin_34133829的博客:【NIO系列】——之Reactor模型

    weixin_34133829的博客:【NIO系列】——之Reactor模型

    作者:[db:作者] 时间:2021-07-30 21:02


    在开篇之前,我们对JavaNIO 的使用方式不做过多介绍,这种API的介绍方式网上太多了,没必要详细介绍,我们假设NIO的使用方式,你能够熟练运用。这是NIO系列第三篇:

    【NIO系列】——之TCP探秘

    【NIO系列】——之IO模型


    通过之前的Unix的IO模型介绍,想必也了解到了5种IO模型。java的NIO是属于同步非阻塞IO,关于IO多路复用,java没有相应的IO模型,但有相应的编程模式,Reactor 就是基于NIO中实现多路复用的一种模式。本文将从以下几点阐述Reactor模式:

    1. reactor 是什么

    2. 为何要用,能解决什么问题

    3. 如何用,更好的方式

    4. 其他事件处理模式


    一、Reactor 是什么

    关于reactor 是什么,我们先从wiki上看下:

    The reactor design pattern is an event handling pattern for handling service requests delivered concurrently to a service handler by one or more inputs. The service handler then demultiplexes the incoming requests and dispatches them synchronously to the associated request handlers.

    从上述文字中我们可以看出以下关键点 :

    1. 事件驱动(event handling)

    2. 可以处理一个或多个输入源(one or more inputs)

    3. 通过Service Handler同步的将输入事件(Event)采用多路复用分发给相应的Request Handler(多个)处理

    自POSA2 中的关于Reactor Pattern 介绍中,我们了解了Reactor 的处理方式:

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

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

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


    关于Reactor Pattern 的OMT 类图设计:


    二、为何要用Reactor

    常见的网络服务中,如果每一个客户端都维持一个与登陆服务器的连接。那么服务器将维护多个和客户端的连接以出来和客户端的contnect 、read、write ,特别是对于长链接的服务,有多少个c端,就需要在s端维护同等的IO连接。这对服务器来说是一个很大的开销。

    1、BIO

    比如我们采用BIO的方式来维护和客户端的连接:

    // 主线程维护连接
      public void run() {
          try {
              while (true) {
                  Socket socket = serverSocket.accept();
                  //提交线程池处理
                  executorService.submit(new Handler(socket));
              }
          } catch (Exception e) {
              e.printStackTrace();
          }
      }
    ?
      // 处理读写服务
      class Handler implements Runnable {
          public void run() {
              try {
                  //获取Socket的输入流,接收数据
                  BufferedReader buf = new BufferedReader(new InputStreamReader(socket.getInputStream()));
                  String readData = buf.readLine();
                  while (readData != null) {
                      readData = buf.readLine();
                      System.out.println(readData);
                  }
              } catch (Exception e) {
                  e.printStackTrace();
              }
          }
      }复制代码
    cs