- IO流和NIO流
- NIO介绍
- nio核心
- nio面向"块"
- nio的非阻塞
- NIO流程图
- java.nio.ByteBuffer
- Buffer参数说明
- Buffer的常用方法:
- 实例Demo
基本区别:
传统IO是面向流的,NIO是面向缓冲的。传统IO是每次从流中读一个或多个字节,直到读取所有字节,它们没有被缓存在任何地方。
NIO是将数据读取到一个稍后处理的缓冲区,需要时可在缓冲区中前后移动,增加了处理过程中的灵活性。
IO与NIO的适用场景:
如果需要管理同时打开的成千上万个连接,这些连接每次只是发送少量的数据,例如聊天服务器,实现NIO的服务器可能是一个优势。
如果你有少量的连接使用非常高的带宽,一次发送大量的数据,也许典型的IO服务器实现可能非常契合。
底层处理:
IO流是每次处理一个或多个字节。
NIO流是以数据块为单位来处理,缓冲区就是用于读写的数据块。
NIO 有三大核心部分:Channel(通道),Buffer(缓冲区), Selector(选择器) 。
Channel和Buffer:NIO是基于通道(Channel)和缓冲区(Buffer)进行操作,数据总是从通道读取到缓冲区中,或者从缓冲区写入到通道中。
Selector:选择器用于监听多个通道的事件(比如:连接打开,数据到达)。因此,单个的线程可以监听多个数据通道。
NIO是 面向缓冲区 ,或者面向 块 编程的。数据读取到一个它稍后处理的缓冲区,需要时可在缓冲区中前后移动,这就增加了处理过程中的灵活性,使用它可以提供非阻塞式的高伸缩性网络
(数据读取到缓冲区后可以前后移动的意思:详细理解下面缓冲区的参数说明和常用方法即可)
Java NIO的非阻塞模式,使一个线程从某通道发送请求或者读取数据,但是它仅能得到目前可用的数据,如果目前没有数据可用时,就什么都不会获取,而不是保持线程阻塞,所以直至数据变的可以读取之前,该线程可以继续做其他的事情。 非阻塞写也是如此,一个线程请求写入一些数据到某通道,但不需要等待它完全写入,这个线程同时可以去做别的事情。(同步异步阻塞非阻塞概念链接: link.)
举例:NIO是可以做到用一个线程来处理多个操作的。假设有10000个请求过来,根据实际情况,可以分配50或者100个线程来处理。不像之前的阻塞IO那样,非得分配10000个。
主要有五个属性:mark,position,limit,capacity和array
mark:记录了当前所标记的索引下标;
position:对于写入模式,表示当前可写入数据的下标,对于读取模式,表示接下来可以读取的数据的下标;
limit:对于写入模式,表示当前可以写入的数组大小,默认为数组的最大长度,对于读取模式,表示当前最多可以读取的数据的位置下标;
capacity:表示当前数组的容量大小;
array:保存了当前写入的数据。
flip():确定缓冲区数据的起始点和终止点,为输出数据做准备(即写入通道)。此时:limit = position,position = 0。
clear():缓冲区初始化,准备再次接收新数据到缓冲区。position = 0,limit = capacity。
remaining():判断postion到limit之间是否还有元素。(查看源码该方法返回的就是 limit - position)
rewind():postion设为0,则mark值无效。
limit(int newLt):设置界限值,并返回一个缓冲区,该缓冲区的界限和limit()设置的一样。
get()和put():获取元素和存放元素。使用clear()之后,无法直接使用get()获取元素,需要使用get(int index)根据索引值来获取相应元素。
//数据从通道读取到缓冲区中,也可以从缓冲区写入到通道中
ByteBuffer respHeader = ByteBuffer.allocate(8);//创建缓冲区,并初始化大小
// 获取响应报文
Socket client = new Socket();//创建通道
InputStream is = client.getInputStream();
byte[] tmpHeader = new byte[8];
int length = 0;
//is.read(tmpHeader) 数据从通道读取到缓存区
while ((respHeader.remaining() != 0) && ((length = is.read(tmpHeader)) != -1)) {
respHeader.put(tmpHeader, 0, length);
tmpHeader = new byte[respHeader.remaining()];
}
respHeader.array();



