BIO、NIO、AIO 区别

liminjun

1、IO介绍

我们通常说BIO是相对于NIO而言的。 BIO是Java初期引入的IO操作模块。 BIO是BlockingIO的缩写。 顾名思义,就是阻塞IO。 AIO是NIO的升级版,提供异步非阻塞IO操作模式。

1.1 BIO、NIO、AIO的区别

BIO 是传统的 java.io 包,它基于流模型,以同步和阻塞方式交互。 也就是说,当读入输入流或输出流时,线程会被阻塞在那里,直到读写动作完成,它们之间的调用是可靠的线性顺序。 它的优点是代码比较简单直观; 缺点是IO效率和可扩展性很低,容易成为应用性能瓶颈。

NIO是在Java 1.4 java.nio Package中引入的,它提供了Channel、Selector、Buffer等新的抽象,可以构建多路同步的非阻塞IO程序,提供更贴近底层操作系统的高性能数据操作模式.

AIO 是 Java 1.7 之后引入的一个包。 它是NIO的升级版。 它提供了异步和非阻塞的IO操作模式,所以人们称之为AIO(异步IO),异步IO是基于事件和回调机制的,即应用操作后直接返回,不会被阻塞在那里. 当后台处理完成后,操作系统会通知相应的线程进行后续操作。

1.2 全面理解IO

传统的IO大致可以分为四种:

1)基于字节操作的输入流和输出流IO

2)基于字符操作的Writer和Reader的IO

3)基于磁盘操作的文件IO

4)基于网络操作的Socket IO

java.net 很多时候,人们也把它归类为同步阻塞IO,因为网络通信也是IO行为。

java.io下面有很多类和接口,但一般都是InputStream、OutputStream、Writer和Reader的子集。 掌握好这四个类和文件的使用,是用好IO的关键。

1.3 IO使用

接下来看一下InputStream、OutputStream、Writer、Reader的继承图和使用示例。

1.3.1 InputStream 用法

继承图和类方法如下:

1

InputStream 使用示例:

1
2
3
4
5
6
InputStream inputStream = new FileInputStream("D:\\log.txt");
byte[] bytes = new byte[inputStream.available()];
inputStream.read(bytes);
String str = new String(bytes, "utf-8");
System.out.println(str);
inputStream.close();

1.3.2 OutputStream的使用

2

1
2
3
OutputStream outputStream = new FileOutputStream("D:\\log.txt",true); // Parameter 2 indicates whether to append, true = append
outputStream.write("Hello, Lao Wang".getBytes("utf-8"));
outputStream.close();

1.3.3 Writer的使用

3

1
2
3
Writer writer = new FileWriter("D:\\log.txt",true); // Parameter 2, whether to append file, true = append
writer.append("Hello, Lao Wang");
writer.close();

1.3.4 Reader的使用

4

1
2
3
4
5
6
7
8
9
10
Reader reader = new FileReader(filePath);
BufferedReader bufferedReader = new BufferedReader(reader);
StringBuffer bf = new StringBuffer();
String str;
while ((str = bufferedReader.readLine()) != null) {
bf.append(str + "\n");
}
bufferedReader.close();
reader.close();
System.out.println(bf.toString());

2、同步、异步、阻塞、非阻塞

2.1 同步与异步

同步是指当一个任务的完成依赖于另一个任务时,只有在依赖任务完成后,依赖任务才能算作完成。 这是一个可靠的任务序列。 要么成功要么失败就是成功,两个任务的状态可以保持一致。 而异步不需要等待依赖任务完成,它只是通知依赖任务要完成什么工作,依赖任务立即执行。 只要你完成整个任务,你就完成了。 至于依赖任务是否真正完成,依赖于它的任务无法确定,因此是一个不可靠的任务序列。 我们可以使用电话和短信作为同步和异步操作的一个很好的比喻。

2.2 阻塞与非阻塞

阻塞和非阻塞主要来自CPU消耗。 阻塞意味着 CPU 停止并等待一个缓慢的操作完成,然后 CPU 完成其他事情。 非阻塞是当执行慢操作时,CPU 做其他事情,当慢操作完成时,CPU 完成后续操作。 虽然从表面上看,非阻塞方式可以明显提高CPU利用率,但它还有另外一个后果,那就是系统中线程切换的增加。 增加的CPU使用时间是否可以补偿系统的切换成本需要仔细评估。

2.3 相同/不同,阻塞/非阻塞组合

有四种相同/不同和阻塞/非阻塞组合,如下表所示:

组合模式 性能分析
同步阻塞 最常用的用法是最简单的。 但是I/O性能普遍较差,大部分CPU处于空闲状态。
同步非阻塞 提高 I/O 性能的常用方法是将 I/O 阻塞模式改为非阻塞模式,特别是当网络 I/O 为长连接且同时没有大量数据传输时,性能改善非常有效。 这种方法一般可以提高I/O性能,但是会增加CPU消耗。 需要考虑增加的I/O性能是否可以弥补CPU的消耗,即系统的瓶颈是在I/O还是CPU。
异步阻塞 这种方法常用于分布式数据库。 例如,当一条记录写入网络的分布式数据库时,一条记录会被同步阻塞,另外两条或三条备份记录会写入其他机器。 这些备份记录通常采用异步阻塞的方式写入。 异步阻塞可以提高网络 I/O 的效率,尤其是在同一数据的多个副本同时写入时。
异步非阻塞 这种组合方式比较复杂,只能在一些非常复杂的分布式情况下使用。 比如集群间的消息同步机制一般采用这种I/O组合方式。 例如,Cassandra 的 Gossip 通信机制是异步和非阻塞的。 适用于将同一数据的多个副本同时传输到集群中的不同机器上。 数据传输量虽小,但非常频繁。 这种网络I/O可以通过这种方式实现最高的性能。

3、优雅的文件读写

在Java 7之前,文件读取如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// Add file
FileWriter fileWriter = new FileWriter(filePath, true);
fileWriter.write(Content);
fileWriter.close();

// read file
FileReader fileReader = new FileReader(filePath);
BufferedReader bufferedReader = new BufferedReader(fileReader);
StringBuffer bf = new StringBuffer();
String str;
while ((str = bufferedReader.readLine()) != null) {
bf.append(str + "\n");
}
bufferedReader.close();
fileReader.close();
System.out.println(bf.toString());

Java 7引入了Files(java.nio Package),大大简化了文件的读写,如下

1
2
3
4
5
6
// Write file (append method: StandardOpenOption.APPEND )
Files.write(Paths.get(filePath), Content.getBytes(StandardCharsets.UTF_8), StandardOpenOption.APPEND);

// read file
byte[] data = Files.readAllBytes(Paths.get(filePath));
System.out.println(new String(data, StandardCharsets.UTF_8));

Files下还有很多好用的方法,比如创建多级文件夹,写起来很方便

1
2
// Create multi (single) layer directory (if there is no creation, there will be no error)
new Files("D://a//b").mkdirs();

4、总结

以上就是IO从1.0到当前版本(这个版本)JDK 8的核心操作,可以看出IO作为一个常见的基础功能,变化很大。 而且,它的使用变得越来越简单。 IO的操作简单易懂。 一进一出,掌握了输入和输出,才能很好的掌握IO。

  • Title: BIO、NIO、AIO 区别
  • Author: liminjun
  • Created at: 2021-10-09 22:49:42
  • Updated at: 2021-10-09 23:23:15
  • Link: https://olldbg.github.io/2021/10/09/io-model/
  • License: This work is licensed under CC BY-NC-SA 4.0.