简介

jdk7中新增了一些与文件(网络)I/O相关的一些api。这些API被称为NIO.2,或称为AIO(AsynchronousI/O)。AIO最大的一个特性就是异步能力,这种能力对socket与文件I/O都起作用。AIO其实是一种在读写操作结束之前允许进行其他操作的I/O处理。AIO是对JDK1.4中提出的同步非阻塞I/O(NIO)的进一步增强。

关于NIO,之前的一篇文章可以看看:java中的NIO

jdk7主要增加了三个新的异步通道:

  • AsynchronousFileChannel:用于文件异步读写;

  • AsynchronousSocketChannel:客户端异步socket;

  • AsynchronousServerSocketChannel:服务器异步socket。

因为AIO的实施需充分调用OS参与,IO需要操作系统支持、并发也同样需要操作系统的支持,所以性能方面不同操作系统差异会比较明显。

前提概念

在具体看AIO之前,我们需要知道一些必要的前提概念。

Unix中的I/O模型

Unix定义了五种I/O模型

  • 阻塞I/O

  • 非阻塞I/O

  • I/O复用(select、poll、linux2.6种改进的epoll)

  • 信号驱动IO(SIGIO)

  • 异步I/O(POSIX的aio_系列函数)

一个戏谑的例子:

如果你想吃一份宫保鸡丁盖饭:

  • 同步阻塞:你到饭馆点餐,然后在那等着,还要一边喊:好了没啊!

  • 同步非阻塞:在饭馆点完餐,就去遛狗了。不过溜一会儿,就回饭馆喊一声:好了没啊!

  • 异步阻塞:遛狗的时候,接到饭馆电话,说饭做好了,让您亲自去拿。

  • 异步非阻塞:饭馆打电话说,我们知道您的位置,一会给你送过来,安心遛狗就可以了。

详情参见文章末尾的他山之石-Unix下五种IO模型。

Reactor与Proactor

  • 两种IO多路复用方案:ReactorandProactor。

  • Reactor模式是基于同步I/O的,而Proactor模式是和异步I/O相关的。

  • reactor:能收了你跟俺说一声。proactor:你给我收十个字节,收好了跟俺说一声。

详情参见文章末尾的他山之石-IO设计模式:Reactor和Proactor对比。

异步的处理

异步无非是通知系统做一件事情。然后忘掉它,自己做其他事情去了。很多时候系统做完某一件事情后需要一些后续的操作。怎么办?这时候就是告诉异步调用如何做后续处理。通常有两种方式:

  • 将来式:当你希望主线程发起异步调用,并轮询等待结果的时候使用将来式;

  • 回调式:常说的异步回调就是它。

以文件读取为例

将来式

将来式用现有的Java.util.concurrent技术声明一个Future,用来保存异步操作的处理结果。通常用Futureget()方法(带或不带超时参数)在异步IO操作完成时获取其结果。

AsynchronousFileChannel会关联线程池,它的任务是接收IO处理事件,并分发给负责处理通道中IO操作结果的结果处理器。跟通道中发起的IO操作关联的结果处理器确保是由线程池中的某个线程产生。

将来式例子

Pathpath=Paths.get("/data/code/github/java_practice/src/main/resources/1log4j.properties");AsynchronousFileChannelchannel=AsynchronousFileChannel.open(path);ByteBufferbuffer=ByteBuffer.allocate(1024);Future