理解Java NIO
5种I/O模型
?????? 说起I/O模型,网络上有一个错误的概念,异步非阻塞/阻塞模型,其实异步根本就没有阻不阻塞之说,异步模型就是异步模型。让我们来看一看Richard Stevens在其UNIX网络编程卷1中提出的5个I/O模型吧。




?????? 由POSIX术语定义,同步I/O操作导致请求进程阻塞,直到I/O操作完成;异步I/O操作不导致请求进程阻塞。5种模型中的前4种都属于同步I/O模型。
Why NIO?
?????? 开始讲NIO之前,了解为什么会有NIO,相比传统流I/O的优势在哪,它可以用来做什么等等的问题,还是很有必要的。
????? 传统流I/O是基于字节的,所有I/O都被视为单个字节的移动;而NIO是基于块的,大家可能猜到了,NIO的性能肯定优于流I/O。没错!其性能的提高要得益于其使用的结构更接近操作系统执行I/O的方式:通道和缓冲器。我们可以把它想象成一个煤矿,通道是一个包含煤层(数据)的矿藏,而缓冲器则是派送到矿藏的卡车。卡车载满煤炭而归,我们再从卡车上获得煤炭。也就是说,我们并没有直接和通道交互;我们只是和缓冲器交互,并把缓冲器派送到通道。通道要么从缓冲器获得数据,要么向缓冲器发送数据。(这段比喻出自Java编程思想)
????? NIO的主要应用在高性能、高容量服务端应用程序,典型的有Apache Mina就是基于它的。
缓冲区?
??????????缓冲区实质上就是一个数组,但它不仅仅是一个数组,缓冲区还提供了对数据的结构化访问,而且还可以跟踪系统的读/写进程。为什么这么说呢?下面来看看缓冲区的细节。?
????????? 讲缓冲区细节之前,我们先来看一下缓冲区“家谱”:

????? 这四个属性总是遵循这样的关系:0<=mark<=position<=limit<=capacity。下图是新创建的容量为10的缓冲区逻辑视图:?
??????????????????
?????
???????
?
?
?????? 将数据从输入通道copy到输出通道的过程应该是这样的:

?????? 讲了这么多,下面来看一段用NIO写的简单服务器代码:?
??????
I/O多路复用模式
???????I/O多路复用有两种经典模式:基于同步I/O的reactor和基于异步I/O的proactor。?
?????? 异步的proactor固然不错,但它局限于操作系统(要支持异步操作),为了开发真正独立平台的通用接口,我们可以通过reactor模拟来实现proactor。
总结
???????本文介绍了I/O的一些基础概念及5种I/O模型,NIO是5种模型中的I/O复用模型;接着进入主题Java NIO,分别讲了NIO中三个最重要的概念:缓冲区、通道、选择器;我们也明白了NIO是如何实现I/O复用模型的。最后讨论了I/O多路复用模式中的两种模式:reactor和proactor,以及如何用reactor模拟proactor。
参考资料
O'Reilly Java NIO?
Richard Stevens《UNIX网络编程 卷1:套接字联网API》?
两种高性能I/O设计模式(Reactor/Proactor)的比较?
Understanding Network I/O?
Understanding Disk I/O - when should you be worried?