• java AIO学习 2016-09-09 17:58:47
    系统I/O 可分为阻塞型, 非阻塞同步型以及非阻塞异步型[1, 2]. 阻塞型I/O意味着控制权只到调用操作结束了才会回到调用者手里. 结果调用者被阻塞了, 这段时间了做不了任何其它事情. 更郁闷的是,在等待IO结果...

    转载http://blog.csdn.net/zhongweijian/article/details/8005444

    系统I/O 可分为阻塞型, 非阻塞同步型以及非阻塞异步型[12]. 阻塞型I/O意味着控制权只到调用操作结束了才会回到调用者手里. 结果调用者被阻塞了, 这段时间了做不了任何其它事情. 更郁闷的是,在等待IO结果的时间里,调用者所在线程此时无法腾出手来去响应其它的请求,这真是太浪费资源了。拿read()操作来说吧, 调用此函数的代码会一直僵在此处直至它所读的socket缓存中有数据到来.

    相比之下,非阻塞同步是会立即返回控制权给调用者的。调用者不需要等等,它从调用的函数获取两种结果:要么此次调用成功进行了;要么系统返回错误标识告诉调用者当前资源不可用,你再等等或者再试度看吧。比如read()操作, 如果当前socket无数据可读,则立即返回EWOULBLOCK/EAGAIN,告诉调用read()者"数据还没准备好,你稍后再试".

    在非阻塞异步调用中,稍有不同。调用函数在立即返回时,还告诉调用者,这次请求已经开始了。系统会使用另外的资源或者线程来完成这次调用操作,并在完成的时候知会调用者(比如通过回调函数)。拿Windows的ReadFile()或者POSIX的aio_read()来说,调用它之后,函数立即返回,操作系统在后台同时开始读操作。

    在以上三种IO形式中,非阻塞异步是性能最高、伸缩性最好的。

    这篇文章探讨不同的I/O利用机制并提供一种跨平台的设计模式(解决方案). 希望此文可以给于TCP高性能服务器开发者一些帮助,选择最佳的设计方案。下面我们会比较 Java, c#, C++各自对探讨方案的实现以及性能. 我们在文章的后面就不再提及阻塞式的方案了,因为阻塞式I/O实在是缺少可伸缩性,性能也达不到高性能服务器的要求。

    两种IO多路复用方案:Reactor and Proactor

    一般情况下,I/O 复用机制需要事件分享器(event demultiplexor [13]). 事件分享器的作用,即将那些读写事件源分发给各读写事件的处理者,就像送快递的在楼下喊: 谁的什么东西送了, 快来拿吧。开发人员在开始的时候需要在分享器那里注册感兴趣的事件,并提供相应的处理者(event handlers),或者是回调函数; 事件分享器在适当的时候会将请求的事件分发给这些handler或者回调函数.

    涉及到事件分享器的两种模式称为:Reactor and Proactor [1]. Reactor模式是基于同步I/O的,而Proactor模式是和异步I/O相关的. 在Reactor模式中,事件分离者等待某个事件或者可应用或个操作的状态发生(比如文件描述符可读写,或者是socket可读写),事件分离者就把这个事件传给事先注册的事件处理函数或者回调函数,由后者来做实际的读写操作。

    而在Proactor模式中,事件处理者(或者代由事件分离者发起)直接发起一个异步读写操作(相当于请求),而实际的工作是由操作系统来完成的。发起时,需要提供的参数包括用于存放读到数据的缓存区,读的数据大小,或者用于存放外发数据的缓存区,以及这个请求完后的回调函数等信息。事件分离者得知了这个请求,它默默等待这个请求的完成,然后转发完成事件给相应的事件处理者或者回调。举例来说,在Windows上事件处理者投递了一个异步IO操作(称有overlapped的技术),事件分离者等IOCompletion事件完成[1]. 这种异步模式的典型实现是基于操作系统底层异步API的,所以我们可称之为“系统级别”的或者“真正意义上”的异步,因为具体的读写是由操作系统代劳的。

    举另外个例子来更好地理解Reactor与Proactor两种模式的区别。这里我们只关注read操作,因为write操作也是差不多的。下面是Reactor的做法:

    • 某个事件处理者宣称它对某个socket上的读事件很感兴趣;
    • 事件分离者等着这个事件的发生;
    • 当事件发生了,事件分离器被唤醒,这负责通知先前那个事件处理者;
    • 事件处理者收到消息,于是去那个socket上读数据了. 如果需要,它再次宣称对这个socket上的读事件感兴趣,一直重复上面的步骤;

    下面再来看看真正意义的异步模式Proactor是如何做的:

    • 事件处理者直接投递发一个写操作(当然,操作系统必须支持这个异步操作). 这个时候,事件处理者根本不关心读事件,它只管发这么个请求,它魂牵梦萦的是这个写操作的完成事件。这个处理者很拽,发个命令就不管具体的事情了,只等着别人(系统)帮他搞定的时候给他回个话。
    • 事件分离者等着这个读事件的完成(比较下与Reactor的不同);
    • 当事件分离者默默等待完成事情到来的同时,操作系统已经在一边开始干活了,它从目标读取数据,放入用户提供的缓存区中,最后通知事件分离者,这个事情我搞完了;
    • 事件分享者通知之前的事件处理者: 你吩咐的事情搞定了;
    • 事件处理者这时会发现想要读的数据已经乖乖地放在他提供的缓存区中,想怎么处理都行了。如果有需要,事件处理者还像之前一样发起另外一个写操作,和上面的几个步骤一样。

    jdk 7中已经内置了AIO的实现,可以参考http://www.iteye.com/topic/472333 这个对aio的分析

    我们试试jdk7的AIO的示例

    服务器端程序


    [java] view plain copy
    1. import java.io.IOException;  
    2. import java.net.InetSocketAddress;  
    3. import java.nio.ByteBuffer;  
    4. import java.nio.channels.AsynchronousChannelGroup;  
    5. import java.nio.channels.AsynchronousServerSocketChannel;  
    6. import java.nio.channels.AsynchronousSocketChannel;  
    7. import java.nio.channels.CompletionHandler;  
    8. import java.util.concurrent.ExecutionException;  
    9. import java.util.concurrent.ExecutorService;  
    10. import java.util.concurrent.Executors;  
    11.   
    12.   
    13. public class EchoAioServer {  
    14.   
    15.     private final int port;  
    16.   
    17.     public static void main(String args[]) {  
    18.         int port = 8000;  
    19.         new EchoAioServer(port);  
    20.     }  
    21.   
    22.     public EchoAioServer(int port) {  
    23.         this.port = port;  
    24.         listen();  
    25.     }  
    26.   
    27.     private void listen() {  
    28.         try {  
    29.             ExecutorService executorService = Executors.newCachedThreadPool();  
    30.             AsynchronousChannelGroup threadGroup = AsynchronousChannelGroup.withCachedThreadPool(executorService, 1);  
    31.             try (AsynchronousServerSocketChannel server = AsynchronousServerSocketChannel.open(threadGroup)) {  
    32.                 server.bind(new InetSocketAddress(port));  
    33.   
    34.                 System.out.println("Echo listen on " + port);  
    35.   
    36.                 server.accept(nullnew CompletionHandler<AsynchronousSocketChannel, Object>() {  
    37.                     final ByteBuffer echoBuffer = ByteBuffer.allocateDirect(1024);  
    38.                     public void completed(AsynchronousSocketChannel result, Object attachment) {  
    39.                         System.out.println("waiting ....");  
    40.                         try {  
    41.                             echoBuffer.clear();  
    42.                             result.read(echoBuffer).get();  
    43.                             echoBuffer.flip();  
    44.                             // echo data  
    45.                             result.write(echoBuffer);  
    46.                             echoBuffer.flip();  
    47. //                            System.out.println("Echoed '" + new String(echoBuffer.array()) + "' to " + result);  
    48.                         } catch (InterruptedException | ExecutionException e) {  
    49.                             System.out.println(e.toString());  
    50.                         } finally {  
    51.                             try {  
    52.                                 result.close();  
    53.                                 server.accept(nullthis);  
    54.                             } catch (Exception e) {  
    55.                                 System.out.println(e.toString());  
    56.                             }  
    57.                         }  
    58.   
    59.                         System.out.println("done...");  
    60.                     }  
    61.   
    62.                     @Override  
    63.                     public void failed(Throwable exc, Object attachment) {  
    64.                         System.out.println("server failed: " + exc);  
    65.                     }  
    66.                 });  
    67.   
    68.                 try {  
    69.                     // Wait for ever  
    70.                     Thread.sleep(Integer.MAX_VALUE);  
    71.                 } catch (InterruptedException ex) {  
    72.                     System.out.println(ex);  
    73.                 }  
    74.             }  
    75.         } catch (IOException e) {  
    76.             System.out.println(e);  
    77.         }  
    78.     }  
    79. }  

    客户端程序


    [java] view plain copy
    1. import java.net.InetSocketAddress;  
    2. import java.nio.ByteBuffer;  
    3. import java.nio.channels.AsynchronousSocketChannel;  
    4. import java.nio.channels.CompletionHandler;  
    5. import java.util.concurrent.ExecutionException;  
    6.   
    7. public class EchoAioClient {  
    8.     private final AsynchronousSocketChannel client ;  
    9.       
    10.     public EchoAioClient() throws Exception{  
    11.        client = AsynchronousSocketChannel.open();  
    12.     }  
    13.       
    14.     public void start()throws Exception{  
    15.         client.connect(new InetSocketAddress("127.0.0.1",8000),null,new CompletionHandler<Void,Void>() {  
    16.             @Override  
    17.             public void completed(Void result, Void attachment) {  
    18.                 try {  
    19.                     client.write(ByteBuffer.wrap("this is a test".getBytes())).get();  
    20.                     System.out.println("send data to server");  
    21.                 } catch (Exception ex) {  
    22.                     ex.printStackTrace();  
    23.                 }  
    24.             }  
    25.   
    26.             @Override  
    27.             public void failed(Throwable exc, Void attachment) {  
    28.                 exc.printStackTrace();  
    29.             }  
    30.         });  
    31.         final ByteBuffer bb = ByteBuffer.allocate(1024);  
    32.         client.read(bb, nullnew CompletionHandler<Integer,Object>(){  
    33.   
    34.             @Override  
    35.             public void completed(Integer result, Object attachment) {  
    36.                  System.out.println(result);  
    37.                  System.out.println(new String(bb.array()));  
    38.             }  
    39.   
    40.             @Override  
    41.             public void failed(Throwable exc, Object attachment) {  
    42.                     exc.printStackTrace();  
    43.                 }  
    44.             }  
    45.         );  
    46.           
    47.   
    48.           
    49.         try {  
    50.             // Wait for ever  
    51.             Thread.sleep(Integer.MAX_VALUE);  
    52.         } catch (InterruptedException ex) {  
    53.             System.out.println(ex);  
    54.         }  
    55.           
    56.     }  
    57.       
    58.     public static void main(String args[])throws Exception{  
    59.         new EchoAioClient().start();  
    60.     }  
    61. }  

    执行server跟client后输出如下:

    server输出:

    [html] view plain copy
    1. Echo listen on 8000  
    2. waiting ....  
    3. done...  

    client输出:

    [html] view plain copy
    1. send data to server  
    2. 14  
    3. this is a test  
    展开全文
  • Java AIO编程入门 2017-06-17 20:37:51
    服务器端:public class Server { //线程池 private ExecutorService executorService; //线程组 private AsynchronousChannelGroup threadGroup; //服务器通道 public AsynchronousServerSocketChannel assc
  • JAVA 中BIO,NIO,AIO的理解 2018-07-21 15:39:45
    java BIO/NIO/AIO 学习 Java BIO学习总结 JAVA 中BIO,NIO,AIO的理解 JAVA中IO技术:BIO、NIO、AIO Java之IO,BIO,NIO,AIO知多少?  最近公司要对项目中既有的项目进行改造,将用到的bio改成spring服务的方式...
  • java BIO NIO AIO 2018-04-05 17:33:58
    1F 说一说I/O 首先来说一下什么是I/O? 在计算机系统中I/O就是输入(Input)和输出(Output)的意思,针对不同的操作对象,可以划分为磁盘I/O模型,网络I/O模型,内存映射I/O, Direct I/O、数据库I/O等,只要具有...
  • 在此,为了学习和记录,也写一篇文章来介绍NIO和AIO。 1. 什么是NIO NIO是New I/O的简称,与旧式的基于流的I/O方法相对,从名字看,它表示新的一套Java I/O标 准。它是在Java 1.4中被纳入到JDK中的,并具有以下...
  • 高并发Java 八 NIO和AIO 2017-04-28 16:01:23
    在此,为了学习和记录,也写一篇文章来介绍NIO和AIO。 什么是NIO NIO是New I/O的简称,与旧式的基于流的I/O方法相对,从名字看,它表示新的一套Java I/O标 准。它是在Java 1.4中被纳入到JDK中的,并具有以下特性: ...
  • java BIO、NIO、AIO详解 2018-08-27 17:29:24
    写得很好的一篇文章,学习下。 https://www.cnblogs.com/diegodu/p/6823855.html   一、了解Unix网络编程5种I/O模型 1.1、阻塞式I/O模型 阻塞I/O(blocking I/O)模型,进程调用recvfrom,其系统调用直到数据...
  • Java BIO、NIO、AIO 学习 2015-08-23 11:17:03
    同步 : 自己亲自出马持银行卡到银行取钱(使用同步IO时,Java自己处理IO读写)。 异步 : 委托一小弟拿银行卡到银行取钱,然后给你(使用异步IO时,Java将IO读写委托给OS处理,需要将数据缓冲区地址和大小传给OS...
  • ()[TOC]一、同步与异步、阻塞与非阻塞1、同步与异步同步与异步的区别在于,数据从内核空间拷贝到用户空间是否由用户线程完成。 – 对于同步来说,分阻塞和非阻塞两种。阻塞的情况,一个线程维护一个链接,该线程...
  • 受误解的Java AIO 2020-01-09 20:35:04
    AIOJava 7 开始提供的新特性,而这个”新特性“到如今都成了陈年老酒还鲜有人去品味它。要知道 Java 7 可是在 2011年7月份发布的,市面上基于 AIO 实现的通信框架竟然寥寥无几,关于这项技术的介绍文章也普遍...
  • JAVA AIO框架简析 代码示例 要点讲解 一、异步IO模型 异步IO则采用“订阅-通知”模式:即应用程序向操作系统注册IO监听,然后继续做自己的事情。当操作系统发生IO事件,并且准备好数据后,在主动通知应用程序,...
  • java面试之io/nio/aio 2019-01-17 17:54:03
    java面试中技术官通常都会对应聘者提些java io这块的面试题 IO方面: 1、IO熟悉吧,你介绍一下IO的体系吧 2、你使用过IO进行文件的操作吗? //------------------------以下是结论部分 Java中I/O操作主要是指使用...
  • non-blocking IO vs async IO and implementation in Java You understand the terms correctly. As noted, "non-blocking async IO" would be redundant. If the underlying I/O mechanism is non-blocking, it do
  • NIO与AIO学习 2019-10-22 17:57:39
    Java NIO 概览 NIO简介: Java NIO 是 java 1.4, 之后新出的一套IO接口NIO中的N可以理解为Non-blocking,不单纯是New。 NIO的特性/NIO与IO区别: 1)IO是面向流的,NIO是面向缓冲区的; 2)IO流是阻塞的,NIO流是不...
  • 高并发Java:NIO和AIO 2016-11-07 14:38:29
    在此,为了学习和记录,也写一篇文章来介绍NIO和AIO。 1. 什么是NIO NIO是New I/O的简称,与旧式的基于流的I/O方法相对,从名字看,它表示新的一套Java I/O标 准。它是在Java 1.4中被纳入到JDK中的,并具有...
  • (二)java BIO/NIO/AIO 学习 2018-07-30 10:15:05
    一、了解Unix网络编程5种I/O模型 1.1、阻塞式I/O模型 阻塞I/O(blocking I/O)模型,进程调用recvfrom,其系统调用直到数据报到达且被拷贝到应用进程的缓冲区中或者发生错误才返回。进程从调用recvfrom开始到它...
  • Java AIO学习 2016-10-27 15:56:05
    转载Reactor and Proactor的内容 系统I/O 可分为阻塞型, 非阻塞同步型以及非阻塞异步型[1, 2]. 阻塞型I/O意味着控制权只到调用操作结束了才会回到调用者手里. 结果调用者被阻塞了, 这段时间了做不了任何...
  • Java BIO、NIO、AIO应用场景 2018-07-10 22:05:44
    2.异步:使用异步IO时,Java将IO读写委托给OS处理,需要将数据缓冲区地址和大小传给OS,完成后OS通知Java处理(回调)。 3.阻塞:使用阻塞IO时,Java调用会一直阻塞到读写完成才返回。 4.非阻塞:使用非阻塞IO时,...
1 2 3 4 5 ... 20
收藏数 5,285
精华内容 2,114