NIO(Non-blocking I/O,在 Java 畛域,也称为 New I/O),是一种同步非阻塞的 I / O 模型,也是 I / O 多路复用的根底。那和一般 IO 有什么区别呢?
一、概述
NIO 是从 Java 1.4 版本开始引入的一个新的 IO API,NIO 反对面向缓冲区的、基于通道的 IO 操作。
原来的 IO 是阻塞式 IO,与 NIO 的比照:
IO | NIO |
---|---|
面向流 | 面向缓冲 |
阻塞 IO | 非阻塞 IO |
无 | 选择器 |
1、面向流和面向缓冲
面向流是每次从流中读取一个或多个字节,直到读取完。读过了就过了。
面向缓冲是把数据先放到缓冲区中,须要读取的时候从缓冲区拿,缓冲区数据读取后还在,还能通过指针挪动读取缓冲区中不同的数据。
2、阻塞 / 非阻塞
阻塞就是不读写数据的时候也要占着线程,不能干别的。非阻塞是不读写的时候该线程能够干别的事件。
3、选择器
容许一个线程治理多个输出通道。
解决数据的流程:
阻塞 IO
二、NIO 根底
Buffer 和 Channel 是规范 NIO 中的外围对象。
- Channel 是对原 IO 中流的模仿,任何起源和目标数据都必须通过一个 Channel 对象
- Buffer 本质上是一个容器对象,发给 Channel 的所有对象都必须先放到 Buffer 中;同样的,从 Channel 中读取的任何数据都要读到 Buffer 中。
一)对于 Buffer
Buffer 蕴含一些要写入或读出的数据。在 NIO 中,所有的数据都是用 Buffer 解决的,它是 NIO 读写数据的直达池。Buffer 本质上是一个数组,提供对数据结构化拜访的性能。
应用 Buffer 读写数据个别有以下四个步骤:
- 写入数据到 Buffer;
- 调用 flip() 办法,从写模式转换为读模式;
- 从 Buffer 中读取数据;
- 调用 clear() 办法(清空);或者 compact() 办法(革除已读数据)。
二)对于 Channel
能够通过 Channel 读取和写入数据。能够把它看做 IO 中的流。然而它和流相比还有一些不同。
- Channel 是双向的,既能够读又能够写,而流是单向的
- Channel 能够进行异步的读写
- 对 Channel 的读写必须通过 buffer 对象
三、案例 demo
上面通过一个案例解说 NIO 的操作过程。
将从一个文件中读取数据,写入到另一个文件中,代码如下
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
public class CopyFileUseNIO {public static void main(String[] args) throws IOException {
String src = "/xxxx/LICENSE.txt";
String dst = "/xxxx/LICENSE-COPY.txt";
FileInputStream fi = new FileInputStream(src);
FileOutputStream fo = new FileOutputStream(dst);
// 取得传输通道 channel
FileChannel inChannel = fi.getChannel();
FileChannel outChannel = fo.getChannel();
// 取得容器 buffer
ByteBuffer buffer = ByteBuffer.allocate(1024);
while (true) {
// 判断是否读完文件
int eof = inChannel.read(buffer); // #1
if (eof == -1) {break;}
// 重设一下 buffer 的 position=0,limit=position
buffer.flip(); // #2
// 开始写
outChannel.write(buffer); // #3
// 写完要重置 buffer,重设 position=0,limit=capacity
buffer.clear(); // #4}
inChannel.close();
outChannel.close();
fi.close();
fo.close();}
}
关注下面有正文的 #1 ~ #4 四个地位。
四个地位代码执行后 buffer 数据如下所示,参考上面的能够帮你更好的了解,几个操作都做了什么事件。
public final Buffer clear() {
position = 0;
limit = capacity;
mark = -1;
return this;
}
四、总结
本节对 NIO 进行了简要介绍。与原 IO 进行了比照,对 NIO 的读写流程进行了介绍,解说了 NIO 重要的概念 buffer 和 channel。所有的数据必须通过 buffer 解决,channel 仅是连贯的管道,不能间接从 channel 中获取数据。
NIO 有非阻塞的个性,不会在读写未结束时继续阻塞线程,当未在读写时,线程能够解决别的事件。
最初提供了读写数据的 demo 帮忙了解。
参考文章:
Java NIO 浅析
Java 常见面试题汇总 ———–Java 根底(NIO 与 IO 的区别)
Java NIO 详解(一)