Bio、Nio与Aio区别整理

本文详细解释了计算机科学中的IO模型,包括阻塞IO、非阻塞IO、同步IO和异步IO的概念及其应用场景。通过生动的例子对比了BIO、NIO和AIO三种模型的特点和优缺点。

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

IO即输入(Input)和输出(Output)

 阻塞:当试图对该文件描述符进行读写时, 如果当时没有东西可读,或者暂时不可写, 程序就进入等待 状态, 直到有东西可读或者可写为止(强迫症,必须这件事做完才能做其他事情,否则一直等待)

非阻塞: 如果没有东西可读, 或者不可写, 读写函数马上返回, 而不会等待。(先取号,可以去做其他事情,叫号后,过来完成该事情)

同步:指的是用户进程触发IO操作并等待或者轮询的去查看IO操作是否就绪(亲力亲为且专注于一件事) 

异步: 异步是指用户进程触发IO操作以后便开始做自己的事情,而当IO操作已经完成的时候会得到IO完成的通知(异步的特点就是通知,JavaIO读写委托给OS处理,需要将数据缓冲区地址和大小传给OS即:指示别人帮自己做事,完成后得到通知

BioNioAio三者比较

名称

说明

应用场景

补充

优点

缺点

Bio

阻塞io

Apache,Tomcat。主要是并发量要求不高的场景.

服务器实现模式为一个连接一个线程

连接数目比较小且固定的架构

模型简单、

编码简单、

性能瓶颈低、不适合高并发

Nio

同步非阻塞io

Nginx,Netty。主要是高并发量要求的场景.

服务器实现模式为一个请求一个线程,即客户端发送的连接请求都会注册到多路复用器上,多路复用器轮询到连接有I/O请求时才启动一个线程进行处理。 

连接数目多且

连接比较短(轻操作)的架构

性能瓶颈高

模型复杂、

编码复杂、

需处理半包问题

Aio

异步非阻塞io

还不是特别成熟,底层也基本是多线程模拟,所以应用场景不多,Netty曾经用了,但又放弃了。

服务器实现模式为一个有效请求一个线程,客户端的I/O请求都是由OS先完成了再通知服务器应用去启动线程进行处理。 

 

连接数目多且连接比较长(重操作)的架构

 

 

假设有这么一个场景,有一排水壶(客户)在烧水。

AIO的做法是,每个水壶上装一个开关,当水开了以后会提醒对应的线程去处理。

NIO的做法是,叫一个线程不停的循环观察每一个水壶,根据每个水壶当前的状态去处理。

BIO的做法是,叫一个线程停留在一个水壶那,直到这个水壶烧开,才去处理下一个水壶。

可以看出AIO是最聪明省力,NIO相对省力,叫一个人就能看所有的壶,BIO最愚蠢,劳动力低下。

进程中的IO调用步骤:

  1. 进程向操作系统请求数据 ;
  2. 操作系统把外部数据加载到内核的缓冲区中; 
  3. 操作系统把内核的缓冲区拷贝到进程的缓冲区 ;
  4. 进程获得数据完成自己的功能 ;

当操作系统在把外部数据放到进程缓冲区的这段时间(即上述的第二,三步),如果应用进程是挂起等待的,那么就是同步IO,反之,就是异步IO,也就是AIO 。

IO模型关系

Nio线程处理速度是否比BIO的快?

不是。改用nio只是让同时处理请求服务的数量增大,但是单个请求处理的时间是一样的。

使用Buffer提高IO效率的原因(这里与IO流里面的BufferedXXStream、BufferedReader、BufferedWriter提高性能的原理一样):IO的耗时主要花在数据传输的路上,普通的IO是一个字节一个字节地传输,
而采用了Buffer的话,通过Buffer封装的方法(比如一次读一行,则以行为单位传输而不是一个字节一次进行传输)就可以实现“一大块字节”的传输。比如:IO就是送快递,普通IO是一个快递跑一趟,采用了Buffer的IO就是一车跑一趟很明显,buffer效率更高,花在传输路上
的时间大大缩短。

Nio与Aio的区别?

AIO是发出IO请求后,由操作系统自己去获取IO权限并进行IO操作;NIO则是发出IO请求后,由线程不断尝试获取IO权限,获取到后通知应用程序自己进行IO操作。

AIO只是帮助你从内核中将数据复制到用户空间中,并调用你传入的回调方法。 
NIO 是需要程序自己从内核中将数据复制到用户空间中,并需要程序自己调用相应的处理逻辑。

Nio线程处理流程

 

其他补充:

1、系统并发量很大,容易出什么问题?

答:内存溢出,cpu处理不过来。

     1.132位系统1个线程对象默认最大需要320kb内存,64位系统默认需要1M内存,业务对象还需要内存,容易造成内存不够。

     1.2过多的线程需要os频繁切换,也大大影响性能。

     1.3Java的new一个对象,调用操作系统的api,都存放在java的堆里。线程创建时有个栈空间,会消耗内存。

2、阻塞对线程池是否有影响?

阻塞等待接收客户端的数据时,这段时间占着线程,而线程池中线程数是有限的,并发量大是,将导致没有线程处理请求,请求的响应时间长,甚至拒绝服务。

3、请求的响应时间长,设置拒绝服务,这个问题是因为服务器的资源用到极致导致的吗?

不是。由于线程池的线程数不多,bio阻塞内一定有阻塞,处理能力存在上限。若不阻塞,并发量很大。

4、阻塞时,可以将线程让给别人吗?

不能让。只有在线程执行完,才能让出。

 

参考:1、https://juejin.im/entry/598da7d16fb9a03c42431ed3

2、https://www.cnblogs.com/doit8791/p/4951591.html

3、https://www.jianshu.com/p/901a6e35b3d9

4、https://www.cnblogs.com/ygj0930/p/6543960.html

5、https://juejin.im/entry/598da7d16fb9a03c42431ed3

6、https://blog.youkuaiyun.com/jijianshuai/article/details/77450746

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值