BIO、NIO、AIO 区别
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 用法
继承图和类方法如下:
InputStream 使用示例:
1 | InputStream inputStream = new FileInputStream("D:\\log.txt"); |
1.3.2 OutputStream的使用
1 | OutputStream outputStream = new FileOutputStream("D:\\log.txt",true); // Parameter 2 indicates whether to append, true = append |
1.3.3 Writer的使用
1 | Writer writer = new FileWriter("D:\\log.txt",true); // Parameter 2, whether to append file, true = append |
1.3.4 Reader的使用
1 | Reader reader = new FileReader(filePath); |
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 | // Add file |
Java 7引入了Files(java.nio Package),大大简化了文件的读写,如下
1 | // Write file (append method: StandardOpenOption.APPEND ) |
Files下还有很多好用的方法,比如创建多级文件夹,写起来很方便
1 | // Create multi (single) layer directory (if there is no creation, there will be no error) |
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.