聊聊java中NIO的2.0版本AIO

在2011年7月28日 , jdk1.7被正式发布 。他的一个最大的亮点就是将原来的NIO类库生成到了NIO2.0 , 也被叫做AIO 。这篇文章将通过案例对AIO进行一个讲解 。
一、IO的演进
在jdk1.4之前 , JAVA中的IO类库实在是超级原始 , 很多我们现在熟知的概念都还没有出现 , 比如说管道、缓冲区等等 。正是由于这些等等原因 , C语言和C++一直都是IO方面的首选 。这是原始的IO方式 , 也叫作BIO , 它的原理很简单 , 我们使用一张图来表示一下:

聊聊java中NIO的2.0版本AIO

文章插图
 
也就是说BIO时代 , 每次有一个客户端连接进来的时候 , 都会有一个新的线程去处理 , 缺点显而易见 , 如果连接比较多的时候 , 我们就要建立大量的线程去一一处理 。
几年之后 , 2002年 , jdk1.4开始被正式发布了 , 做出的一个巨大的改变就是新增了NIO包 。它提供了很多异步的IO操作方法 , 比如说缓冲区ByteBuffer、Pipe、Channel还有多路复用器Selector等等 。新的NIO类库的出现 , 极大地促进了java对异步非阻塞式编程的发展 。NIO的原理也是很简单 。在这里同样使用一张图来演示一遍:
聊聊java中NIO的2.0版本AIO

文章插图
 
现在我们可以看到 , 所有的客户端连接都可以只用一个线程就可以实现了 。
不过时代总是在一点一点的变化 , 逐渐的java官方为我们提供的NIO类库越来越不能满足需求 , 比如说不支持异步文件读写操作、没有统一的文件属性等等 。于是过了几年 , 在2011年7月28日 , 官方将用了将近十年的NIO类库做了升级 , 也被称为NIO2.0 。后来也叫作AIO 。AIO的原理是在之前的基础上进行的改进 , 意思是异步非阻塞式IO , 也就是说你的客户端在进行读写操作的时候 , 只需要给服务器发送一个请求 , 不用一直等待回答就可以去做其他的事了 。
下面我们使用代码敲一遍来看看如何实现AIO 。
二、AIO的实现
这个案例很简单 , 就是服务端和客户端一个简单的通信 。我们先把代码写好 , 然后再去分析代码的含义 。
1、服务端
第一步:定义Server启动类
聊聊java中NIO的2.0版本AIO

文章插图
 
 
在这里我们定义了一个AIOServerHandle线程去处理服务器端的逻辑 , 在这里我们还休眠了很长时间 , 这是为了避免没有客户端连接时 , 程序运行结束 。现在我们最主要的就是AioServerHandle的代码逻辑了 。
第二步:AioServerHandle类实现
 
聊聊java中NIO的2.0版本AIO

文章插图
 
 
 
我们分析一下这段代码 , 首先我们定义了一个AsynchronousServerSocketChannel , 他表示的就是异步的ServerSocketChannel 。然后我们在构造方法中打开链接 , 绑定地址和端口 。最后再run方法中new了一个AcceptCompleteHandler来处理接入的客户端 。现在就像踢皮球一样 , 真正的处理逻辑又给了新的类AcceptCompleteHandler , 我们再来看 。
第三步:AcceptCompleteHandler的实现
 
聊聊java中NIO的2.0版本AIO

文章插图
 
 
聊聊java中NIO的2.0版本AIO

文章插图
 
 
聊聊java中NIO的2.0版本AIO

文章插图
 
第一部分:
通过构造方法来接受传递过来的AsynchronousServerSocketChannel 。
第二部分第一小节:
serverSocketChannel继续接受传递过来的客户端 , 为什么呢?因为调用了AsynchronousServerSocketChannel的accept方法之后 , 如果有新的客户端连接进来 , 系统会回调我们的CompletionHandler得completed方法 。但是一个AsynchronousServerSocketChannel往往能接受成千上万个客户端 , 所以在这里继续调用了Accept方法 。以便于接受其他客户端的链接 。
第二部分第二小节:
channel.read方法读取客户端传递过来的数据 , 而且在内部还有一个channel.write方法 , 表示返回给客户端的信息 。代码逻辑是一样的 。


推荐阅读