JAVA中的BIO、NIO、AIO是什么?

本文详细介绍了Java中的BIO、NIO和AIO三种IO模型,分析了它们的特点、工作原理及在不同场景下的适用性。BIO是同步阻塞,适合连接数目小且固定的架构;NIO是同步非阻塞,适用于连接数目多且短的架构,通过Channel、Buffer和Selector实现多路复用;AIO是异步非阻塞,适用于连接数目多且长的架构,利用OS完成IO操作并回调通知。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、前言

最近面试时遇到了面试官问BIO、NIO、AIO相关的问题,当时有些深入点的问题没有答上来,这里给大家解释一下这三种IO的意义与关系。

二、了解IO流

Java中的流分为两种,一种是字节流,另一种是字符流,分别由四个抽象类来表示(每种流包括输入和输出两种所以一共四个):InputStream,OutputStream,Reader,Writer。Java中其他多种多样变化的流均是由它们派生出来的。
字符流和字节流是根据处理数据的不同来区分的。字节流按照8位传输,字节流是最基本的,所有文件的储存是都是字节(byte)的储存,在磁盘上保留的并不是文件的字符而是先把字符编码成字节,再储存这些字节到磁盘。

  1. 字符流可用于任何类型的对象,包括二进制对象,而字符流只能处理字符或者字符串。读文本的时候用字符流,例如txt文件。
  2. 节流提供了处理任何类型的IO操作的功能,但它不能直接处理Unicode字符,而字符流就可以。读非文本文件的时候用字节流,例如mp3。

IO的方式通常分为几种,同步阻塞的BIO、同步非阻塞的NIO、异步非阻塞的AIO。

三、BIO

Block IO 同步阻塞式 IO,就是我们平常使用的传统 IO,它的特点是模式简单使用方便,并发处理能力低。

这是一个传统的连接模式,在服务器当中的实现模式是一个连接一个线程,这样的模式很明显的一个缺陷是:由于客户端连接数与服务器线程数成正比关系,可能造成不必要的线程开销,严重的还将导致服务器内存溢出。这种情况可以通过线程池机制改善,但并不能从本质上消除这个弊端。

那么当出现高并发场景时该怎么办?所以就有了下面的NIO。

四、NIO

JDK1.4以后开始,JDK引入的新的IO模型NIO,Non IO 同步非阻塞 IO,是传统 IO 的升级,客户端和服务器端通过 Channel(通道)通讯,实现了多路复用。

Channel(通道):通道是双向的,可读也可写,而流的读写是单向的。无论读写,通道只能和Buffer交互。因为 Buffer,通道可以异步地读写。
Buffer(缓冲区):Buffer是一个对象,它包含一些要写入或者要读出的数据
Selector(选择器):选择器用于使用单个线程处理多个通道。因此,它需要较少的线程来处理这些通道。线程之间的切换对于操作系统来说是昂贵的。 因此,为了提高系统效率选择器是有用的。
就是说加了三个功能来解决bio中的单线程一对多的问题,而服务器的实现模式是多个请求一个线程,即请求会注册到多路复用器Selector上,多路复用器轮询到连接有IO请求时才启动一个线程处理。
Java NIO: 单线程管理多个连接。
但是其维护成本高,容易出现bug,项目大了之后消耗成本

五、AIO

JDK1.7发布了NIO2.0也可以说是Nio的加强版,Asynchronous IO 是 NIO 的升级,也叫 NIO2,实现了异步非堵塞 IO 模型,异步 IO 的操作基于事件和回调机制。

异步 IO 是基于事件和回调机制实现的,也就是应用操作之后会直接返回,不会堵塞在那里,当后台处理完成,操作系统会通知相应的线程进行后续的操作。

这就是真正意义上的异步非阻塞,服务器的实现模式为多个有效请求一个线程,客户端的IO请求都是由OS先完成再通知服务器应用去启动线程处理(回调)。

六、各IO模型之间的关系

  1. BIO:同步并阻塞,服务器实现模式为一个连接一个线程,即客户端有连接请求时服务器端就需要启动一个线程进行处理,如果这个连接不做任何事情会造成不必要的线程开销,当然可以通过线程池机制改善。
  2. NIO:同步非阻塞,服务器实现模式为一个请求一个线程,即客户端发送的连接请求都会注册到多路复用器上,多路复用器轮询到连接有I/O请求时才启动一个线程进行处理。
  3. AIO:异步非阻塞,服务器实现模式为一个有效请求一个线程,客户端的I/O请求都是由OS先完成了再通知服务器应用去启动线程进行处理。

场景适用:

  1. BIO方式适用于连接数目比较小且固定的架构,这种方式对服务器资源要求比较高,并发局限于应用中,JDK1.4以前的唯一选择,但程序直观简单易理解。
  2. NIO方式适用于连接数目多且连接比较短(轻操作)的架构,比如聊天服务器,并发局限于应用中,编程比较复杂,JDK1.4开始支持。
  3. AIO方式使用于连接数目多且连接比较长(重操作)的架构,比如相册服务器,充分调用OS参与并发操作,编程比较复杂,JDK7开始支持。

七、总结

  1. BIO是一个连接一个线程。
  2. NIO是一个请求一个线程。
  3. AIO是一个有效请求一个线程。

同步:
使用同步IO时,Java自己处理IO读写。

也就是必须一件一件事做,等前一件做完了才能做下一件事
(提交请求->等待服务器处理->处理完返回 这个期间客户端浏览器不能干任何事 )

异步:
使用异步IO时,Java将IO读写委托给OS处理,需要将数据缓冲区地址和大小传给OS,完成后OS通知Java处理(回调)。

请求通过事件触发->服务器处理(这是浏览器仍然可以作其他事情)->处理完毕

阻塞:
使用阻塞IO时,Java调用会一直阻塞到读写完成才返回。

阻塞就是说在煮水的过程中,你不可以去干其他的事情(性能和可靠性都不好)

非阻塞:
使用非阻塞IO时,如果不能立马读写,Java调用会马上返回,当IO事件分发器通知可读写时在进行读写,不断循环直到读写完成。

非阻塞就是在同样的情况下,可以同时去干其他的事情(对于低负载、低并发的应用程序)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

大头程序员不头大

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值