(from:http://developer.51cto.com/art/201112/306489.htm)

以下描述,为了说明问题,就提提历史(类似的东西,网上一搜一大把,但是希望你能在这里止步,知道到底是怎么回事。如果还是不清楚,咱就站内沟通!)。

在我(刚)看nio的这段时间里,主要接触了几个东西,就是关于server和client。java之前的io完全可以胜任,但是效率不高,为何效率不高呢?

===============history==start===============
//TODO:finish the old style of server and socket data transion.
ServerSocket socket = new ServerSocket(80);
while (true) {
final Socket connection = socket.accept();
handleRequest(connection);
}
===============history==end in the future================

在上面的代码片段中,我们只能是一个request一个的进行处理。这使得所有的请求都阻塞了。如果我们再改变一下,将handleRequest方法封装到线程中处理:

  1. if(connection = null){
  2. new Thread(new Runnable(){
  3. public void run(){
  4. handleRequest(connection);
  5. }
  6. public void handleRequest(Socket conn){
  7. //do actions
  8. }
  9. }).start();
  10. }

服务器端的资源是有限的,我们这里仅仅是从线程角度来扩展,但是这种处理依然是阻塞的处理方式。首先,仅仅是建立连接(socket),就占用了服务器的线程资源。如果客户端还没有发出相应的数据请求,那么服务器就要一直等待他们的数据流过来,然后再进行读取,如此往复。。。一直都blocking。服务器处在一个高负荷状态中。

NIO出来之后,进入改革开放时期,有了这么几个角色,ServerSocketChannel,SelectionKey,Selector。

这几个角色都是做什么用的呢?需要了解一下reactor模式(反应堆模式)。

作为服务端,如果什么操作都要依赖于客户端,很多操作都阻塞,如上面的代码片段所示。reactor模式提供了一种很好的事件处理机制,以分离事件处理对象与事件之间的耦合。如下图示(详细请看参考资料(1)):

说明:

Acceptor就是我们Server端的主要任务消化者;

Initiation Dispatcher是事件(Event)的分发者;

HTTP Handler是具体操作人。

首先,在Initiation Dispatcher中注册一个acceptor(1:register Acceptor),这个Acceptor是跟事件绑定的,它仅仅关心某种事件(event)。

Initiation Dispatcher不断地循环获取请求过来的事件(2:handle events),如果发现有对应Acceptor关心的事件(3:connect),通知Acceptor有事件发生(4:new connection)。

Acceptor针对此事件进行处理,创建了新的HTTP Handler((5:create handler))

一轮事件获取和分发完成。

那么handler是不是就抓住这个connection不放,然后一直苦苦等待数据流的到来呢?

不是的,它也是将自己和自己关心的事件注册到Initiation Dispatcher。如果Initiation Dispatcher在handle Events时发现了它关心的事件,那么就会交由它去进行相应处理。如下图示,在连接完成后,browser提交的get请求,handler的处理过程:

这里面尤其要注意到,2:read ready,之后才read request,也就是说,handler在dispatcher中注册了自己关心的事件(READ),然后在写的时候,也是类似情况。

以上的过程就实现了非阻塞的处理方式,客户端的连接可以非阻塞(这是意思是,acceptor不必一直苦苦等候),然后对客户端过来的request内容,也是非阻塞(这里是不必苦苦等待其数据的到来),都是不必一直眼巴巴的看着那个连接,那些数据,而是如果有我关心的事件了,我再进行处理,期间完全相信Initiation Dispatcher就行了。

这里有一点要注意,就是现在的reactor模式都是建立在操作系统的基础上实现的,不同的操作系统有不同的实现方式。而且都不支持多线程(针对Initiation Dispatcher而言)。

有了上面的理解之后,来给NIO中的对象跟reactor的对象对个象。

Acceptor:ServerSocketChannel;

Initiation Dispatcher:Selector;

HTTP Handler:针对SocketChannel进行实际处理的个性化对象;

Events:在SelectionKey中:

static int OP_ACCEPT 
          Operation-set bit for socket-accept operations.
static int OP_CONNECT 
          Operation-set bit for socket-connect operations.
static int OP_READ 
          Operation-set bit for read operations.
static int OP_WRITE 
          Operation-set bit for write operations.

Operation-set bit for write operations. 经过上面的描述,我们就可以写出基于NIO的非阻塞Server啦。具体的代码示例大家可以看参考资料

参考资料:

(1)华盛顿大学计算机科学的一篇关于proactor的论文,非常详细。同时这篇文章中还有 reactor的改进版proactor,各位可以一饱眼福。

(2)简单的NIO server实现代码,但是这个代码中在写的部分有些瑕疵,各位根据上面的描述,可以考虑一下有何问题。

在这个代码中,还有一个要注意的地方,就it.remove(),因为某个key在处理过后要删除,否则,这个key将一直处于active状态。

Java NIO的多路复用及reactor的更多相关文章

  1. java NIO的多路复用及reactor模式【转载】

    关于java的NIO,以下博客总结的比较详细,适合初学者学习(http://ifeve.com/java-nio-all/) 下面的文字转载自:http://www.blogjava.net/hell ...

  2. Java多线程:Linux多路复用,Java NIO与Netty简述

    JVM的多路复用器实现原理 Linux 2.5以前:select/poll Linux 2.6以后: epoll Windows: IOCP Free BSD, OS X: kqueue 下面仅讲解L ...

  3. 【转载】高性能IO设计 & Java NIO & 同步/异步 阻塞/非阻塞 Reactor/Proactor

    开始准备看Java NIO的,这篇文章:http://xly1981.iteye.com/blog/1735862 里面提到了这篇文章 http://xmuzyq.iteye.com/blog/783 ...

  4. java NIO中的Reactor相关知识汇总 (转)

    一.引子 nio是java的IO框架里边十分重要的一部分内容,其最核心的就是提供了非阻塞IO的处理方式,最典型的应用场景就是处理网络连接.很多同学提起nio都能说起一二,但是细究其背后的原理.思想往往 ...

  5. I/O模型之四:Java 浅析I/O模型(BIO、NIO、AIO、Reactor、Proactor)

    目录: <I/O模型之一:Unix的五种I/O模型> <I/O模型之二:Linux IO模式及 select.poll.epoll详解> <I/O模型之三:两种高性能 I ...

  6. 从I/O多路复用到Netty,还要跨过Java NIO包

    本文是Netty系列第4篇 上一篇文章我们深入了解了I/O多路复用的三种实现形式,select/poll/epoll. 那Netty是使用哪种实现的I/O多路复用呢?这个问题,得从Java NIO包说 ...

  7. Java NIO 与 基于reactor设计模式的事件处理模型

    Java NIO非堵塞应用通常适用用在I/O读写等方面,我们知道,系统运行的性能瓶颈通常在I/O读写,包括对端口和文件的操作上,过去,在打开一个I/O通道后,read()将一直等待在端口一边读取字节内 ...

  8. Java网络编程和NIO详解2:JAVA NIO一步步构建IO多路复用的请求模型

    Java网络编程与NIO详解2:JAVA NIO一步步构建IO多路复用的请求模型 知识点 nio 下 I/O 阻塞与非阻塞实现 SocketChannel 介绍 I/O 多路复用的原理 事件选择器与 ...

  9. Java NIO学习与记录(八): Reactor两种多线程模型的实现

    Reactor两种多线程模型的实现 注:本篇文章例子基于上一篇进行:Java NIO学习与记录(七): Reactor单线程模型的实现 紧接着上篇Reactor单线程模型的例子来,假设Handler的 ...

随机推荐

  1. Android - 分享内容 - 接收其他APP的内容

    就象程序可以发送数据给其他程序,所以也可以接收其他程序的数据.想一下用户如何和程序交互,以及想从其他程序接收什么样类型的数据.例如,一个社交程序可能对接收其他程序的文字(比如有趣的网址)感兴趣.Goo ...

  2. configure.ac:20: error: Autoconf version 2.65 or higher is required

    安装thrift例如,下面的问题出现: configure.ac:20: error: Autoconf version 2.65 or higher is required wget http:// ...

  3. Oracle中merge into的使用 (转)

    该命令使用一条语句从一个或者多个数据源中完成对表的更新和插入数据. ORACLE 9i 中,使用此命令必须同时指定UPDATE 和INSERT 关键词,ORACLE 10g 做了如下改动. 1.ins ...

  4. Snail—ORACLE基础之事务学习(五)

    ---------------事务---当运行到commit时 事务才算是完毕,不然 会运行rollback操作. declare v_money acount.money%type:=1223; e ...

  5. windows下VC界面 DIY系列1----写给想要写界面的C++程序猿的话

    非常早就想写关于C++ UI开发的一系列博文,博客专栏刚审核通过,就立即開始刷博文,不能辜负自己的一番热血,我并非写界面的高手,仅仅想通过写博文提高我自己的技术积累,也顺便帮助大家解决界面开发的瓶颈. ...

  6. vs2015基于VisualStudioOnline协同工作流程

    项目负责人登陆自己的vsonline新建项目就不多说了. 直接从邀请队友开始 项目负责人操作 被邀请的邮箱务必是可以登录visualstudio的邮箱 发送邀请后,被邀请人登陆自己的邮箱,查看邀请人发 ...

  7. struts详细解释拦截器

    1.拦截器:Struts2拦截器将一个Action要么Action的方法.之前或截取后场,和Struts2拦截器是可插拔,拦截器AOP一种实现. WebWork:拦截器是动态拦截Action调用的对象 ...

  8. HDFS Safemode问题

    处于safemode的集群是无法接收不论什么写操作的,包含创建文件夹.删除文件.改动文件.上传文件等等. 关于safemode,在http://www.iteblog.com/archives/977 ...

  9. C#中的动态特性

    众所周知,C#和Java一样,都是一门静态语言.在C# 4.0之前,想要和动态语言(诸如Python.Javascript等)进行方便地互操作是一件不太容易的事情.而C# 4.0为我们带来的dynam ...

  10. jquery.validate.unobtrusive

    ASP.NET MVC Unobtrusive JavaScript 实现 onfocusout 验证, onfocusin 清除错误 在 ASP.NET MVC 中启用 Unobtrusive Ja ...