什么是NIO
顾名思义N:New I/O;在JDK1.4发布的时候,为Java语言带来了有别与传统I/O的操作方式,提高了读写速率和设备利用率;但是此API只能进行同步阻塞,同步非阻塞,还不能完全利用及其的硬件,在JDK1.7发布时,带来了NIO2.0,它提供了异步I/O操作方式.
SUN官方标榜的特性如下:
- 为所有原始类型提供缓存(Buffer)支持
- 字符集编码解决方案
- Channel:一个新的原始I/O抽象
- 支持所和内存映射文件的文件访问接口
- 提供多路(non-bloking)非阻塞式的高伸缩性网络I/O
同步阻塞,同步非阻塞,异步阻塞,异步非阻塞
将以一个简单的例子来阐述这几个名词,如有不对或不合适的地方请指正;
在上图中,总结起来实际上是两个操作
1.发起买票请求(发起I/O请求)—–>是否阻塞
2.实际的买票操作(实际的I/O操作)—–>是否同步
Java NIO 核心组件
IO分为读和写操作,传统的IO都基于Stream,有InputStream和OutputStream之分,而NIO基于Channel,Channel没有InputStream和OutputStream,因为她是双向的,将数据写入Buffer或者从Buffer中读取数据
Java NIO中最常用的通道实现是如下几个,可以看出跟传统的 I/O 操作类是一一对应的。
FileChannel:读写文件
DatagramChannel: UDP协议网络通信
SocketChannel:TCP协议网络通信
ServerSocketChannel:监听TCP连接
Buffer
NIO中并没有向传统IO基于byte数组,而是基于一个被封装过的Buffer类,通过Buffer类中所提供的API,我们可以操作数据.
与Java基本类型相对应,NIO提供了多种 Buffer 类型,如ByteBuffer、CharBuffer、IntBuffer等,区别就是读写缓冲区时的单位长度不一样(以对应类型的变量为单位进行读写)。
在Buffer类中有几个非常重要的属性,源码如下:
// Invariants: mark <= position <= limit <= capacity
private int position = 0;
private int limit;
private int capacity;
在对Buffer进行读/写的过程中,position会往后移动,而 limit 就是 position 移动的边界。由此不难想象,在对Buffer进行写入操作时,limit应当设置为capacity的大小,而对Buffer进行读取操作时,limit应当设置为数据的实际结束位置。(注意:将Buffer数据 写入 通道是Buffer 读取 操作,从通道 读取 数据到Buffer是Buffer 写入 操作)
主要API
/**
*清除Buffer
*/
public final Buffer clear() {
position = 0;
limit = capacity;
mark = -1;
return this;
}
/**
*设置 limit 为 position 的值,
*然后 position 置为0。对Buffer进行读取操作前调用。
*/
public final Buffer flip() {
limit = position;
position = 0;
mark = -1;
return this;
}
/**
*仅仅将 position 置0。
*一般是在重新读取Buffer数据前调用,
*比如要读取同一个Buffer的数据写入多个通道时会用到。
*/
public final Buffer rewind() {
position = 0;
mark = -1;
return this;
}
/**
*返回limit和position之间的元素
*/
public final int remaining() {
return limit - position;
}