定义:
NIO:是从jdk1.4提出的,本意是New IO(相对于传统的IO),也叫 No Blocked IO(只相对于网络IO),它的出现弥补传统IO的不足,提出了更加高效的方式。
NIO对于网络IO而言:
jdk1.4:采用了基于select/poll的多路复用IO模型。
jdk1.5及以上:采用了基于epoll的多路复用IO模型。
IO模型可查看:详解Unix5种IO模型
NIO对于文件IO而言:
NIO对基于文件的IO还是阻塞模型的IO。只有基于网络IO才是非阻塞的。
NIO的新特性:
- 基于通道(Channel)和缓冲区(Buffer)操作
- 通道(Channel):一个新的、原始的IO抽象。
- 缓冲区支持(Buffer):为所有的原始类型提供缓冲区支持。也就是说NIO是强制基于通道和缓冲区操作的。
- 具体操作:数据从通道读到缓冲区,数据从缓冲区写入通道(用户进程角度)。
- 非阻塞(针对网络IO)
- 提供多路复用、非阻塞的IO操作,即当前线程从通道读取数组到缓冲区时,或者把缓冲区数据写入到通道时,线程依然可以进行其他事情。
- 选择器(selectors)(针对网络IO)
- 用户监听多个通道的事件,如:连接打开,数据到达等,单个线程可监听多个数据通道。
- 其他
- 提供字符集编码、解码解决方案:java.nio.Charset。
- 支持锁和内存映射文件的文件访问接口。
- …
核心组件:
- 通道(Channel):Java NIO的数据来源,可以是网络,也可以是本地磁盘。表示打开到IO设备(文件、套接字)的连接。
- 缓冲区(Buffer):数据读写的中转区。用于容纳数据。
- 选择器(Selectors):异步IO的核心类,可以实现异步非阻塞IO,一个Selectors可以管理多个通道Channel。
一个复制文件的小demo:
/**
* @author YeHaocong
* @decription 一个NIO的Demo,完成对文件的复制
* @Date 2020/5/18 18:52
*/
public class NIOFirstDemo {
public static void main(String[] args) {
try (FileInputStream fis = new FileInputStream("test_nio1.txt");
FileOutputStream fos = new FileOutputStream("test_nio1_cp.txt")){
//获取通道,连接源节点和目标节点,通道本身不存储任何数据,因此需要缓冲区配合传输。
FileChannel fisChannel = fis.getChannel();
//获取通道,连接源节点和目标节点,通道本身不存储任何数据,因此需要缓冲区配合传输。
FileChannel fosChannel = fos.getChannel();
//创建缓冲区,并分配1024字节。
ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
//把文件的数据通过通道传输写到ByteBuffer缓冲区中
fisChannel.read(byteBuffer);
//把缓冲区该为读模式。
byteBuffer.flip();
//读取byteBuffer里面的数据通过输出流通道写到文件中
fosChannel.write(byteBuffer);
//清空缓冲区
byteBuffer.clear();
//关闭通道与流
fisChannel.close();
fosChannel.close();
fis.close();
fos.close();
}catch (IOException e){
}
}
}
IO和NIO的区别:
类型 | 面向操作域 | 处理数据 | IO阻塞/非阻塞(基于网络IO) |
---|---|---|---|
Java IO | 可以面向缓冲区,也可以直接面向数据源,使用流进行传输 | 没有缓冲区的话是直接读取字节或者字符,并且无法前后移动数据流中的数据 | 阻塞:当一个线程在读/写时,当数据完全被读取/写入或者数据没有准备好时,线程不能做其他任务,只能一直阻塞等待,知道数据准备好后才能继续。 |
Java NIO | 强制通道和缓冲区 | 先读取数据到缓冲区,并且可以前后移动数据量中的数据 | 非阻塞:当一个线程在读/写时,当数据完全被读取/写入或者数据没有准备好时,线程可以做其他任务(控制其他通道),知道数据准备好后再切换回该通道。继续读取、写入。 |