拜托,请别再问我 BIO,NIO,AIO 了!

JAVA herman 281浏览
公告:“业余草”微信公众号提供免费CSDN下载服务,关注业余草微信公众号,添加作者微信:xmtxtt,发送下载链接帮助你免费下载!
本博客日IP超过1300,PV 1800 左右,急需赞助商。
打开支付宝首页搜“567452957”领红包,间接赞助博主,谢谢!

这是一个面试中经常被问到的问题,也是高频面试题。我本来是不想写这方面的内容的,怕误导大家。但是奈何总有网友给我私信,想让我简单的解释一下。

所以,就有了本文。其中可能有部分描述不准确或者错误的地方,大家留言,共同交流,共同进步!

BIO,NIO,AIO 这三个名词中都带了一个“IO”。那我们就先看看什么是“IO”。

IO

IO 其实就是 INPUT 和 OUPUT 的简称。与 IO 相关的还有“IO流”,就是说以流的形式进行“IO”。还有就是“IO读写”,很多老司机都搞不清什么是 INPUT 和 OUPUT。

这个 INPUT 和 OUPUT 其实很简单,以内存为目标,数据进内存叫 In,出内存叫 Out。以前我的老师都经常搞错!

明白 IO 后,我们在看来 BIO。

BIO

即 Blocking IO,阻塞式 IO。也有人称它为同步阻塞 IO,为什么加了个同步呢?我下面会讲。

IO 模型矩阵

阻塞 IO,说白了就是数据的读取写入必须阻塞在一个线程内等待其完成。

为什么也称为同步阻塞 IO 呢?因为操作 IO 有两个阶段,一个内核,一个是用户空间。

所谓同步阻塞 IO,就是说,这两个阶段都被阻塞了。比如,一个 UDP 数据包,在网络传输过程中或数据包还不完整时,kernel 就会被阻塞,等待足够的数据到来。也就是说数据被拷贝到操作系统内核的缓冲区中是需要一个过程的。而在用户进程这边,整个进程会被阻塞。当 kernel 一直等到数据准备好了,它就会将数据从 kernel 中拷贝到用户内存,然后 kernel 返回结果,用户进程才解除 block 的状态,重新运行起来。

还搞不懂,就看下面这个图,画的其实不是很好。

BIO 数据操作模型

这里面有两个 block,所以,有人把 BIO 称为同步阻塞 IO,是没错的。同步和异步你可以看作是针对应用程序和内核的交互而言的就行了。

NIO

NIO,nonblocking IO,也叫做 new IO,因为是 NIO 是 JDK 1.4 的 java.nio.* 包中引入的新 I/O 库,目的是提高速度,也是对之前的 BIO 一个补充完善。

在 BIO 模型中,这种 IO 效率太低了,如果需要并发处理多个 I/O 请求,那就需要多线程来支持。我不可能开无限个线程吧,线程开的越多 CPU 切换就成了问题。

所以,人们想到了一种新的实现,New IO。NIO 使用了多路复用器机制,以 socket 使用来说,多路复用器通过不断轮询各个连接的状态,只有在 socket 有流可读或者可写时,应用程序才需要去处理它,在线程的使用上,就不需要一个连接就必须使用一个处理线程了,而是只是有效请求时(确实需要进行 I/O 处理时),才会使用一个线程去处理,这样就避免了 BIO 模型下大量线程处于阻塞等待状态的情景。

何谓多路复用?你可以这样理解,就是多条线路上的请求,我们只用一个或者少量的线程来检查各路请求的连接状态,只有在某条线路上有可读或可写的数据时,在开线程去处理。

这样做了之后,效率确实提升了不少。但是还不完美,所以就有了 AIO。

AIO

AIO 就是 Asynchronous I/O,异步非阻塞 I/O。Java AIO 就是 Java 作为对异步 IO 提供支持的 NIO2,Java NIO2 (JSR 203)定义了更多的 New I/O APIs,NIO2 在 2003 年被提出,直到 2011 年才发布, 最终在 JDK 7 中才实现。

AIO 相对于 NIO 的区别在于,NIO 需要使用者线程不停的轮询 IO 对象,来确定是否有数据准备好可以读了,而 AIO 则是在数据准备好之后,才会通知数据使用者,这样使用者就不需要不停地轮询了。当然 AIO 的异步特性并不是 Java 实现的伪异步,而是使用了系统底层 API 的支持,在 Linux/Unix 系统下,采用了 epoll IO 模型,而 windows 系统下则是使用了 IOCP 模型。

区别与对比

BIO、NIO、AIO 三者之间的区别与联系,如下图所示:

BIO、NIO、AIO

关于 IO 模型划分,不是本文的关注点。大家可以多看看《Unix网络编程》这本书。

IO 模型的划分

最后,解释几个名词。

  • 同步:指的是用户进程触发 I O操作并等待或者轮询的去查看 IO 操作是否就绪
  • 异步:异步是指用户进程触发 IO 操作以后便开始做自己的事情,而当 IO 操作已经完成的时候会得到 IO 完成的通知(异步的特点就是通知)
  • 阻塞:所谓阻塞方式的意思是指,当试图对该文件描述符进行读写时,如果当时没有东西可读,或者暂时不可写,程序就进入等待状态,直到有东西可读或者可写为止
  • 非阻塞:非阻塞状态下,如果没有东西可读,或者不可写,读写函数马上返回,而不会等待

参考资料

业余草公众号

最后,欢迎关注我的个人微信公众号:业余草(yyucao)!可加QQ1群:135430763(2000人群已满),QQ2群:454796847(已满),QQ3群:187424846(已满)。QQ群进群密码:xttblog,想加微信群的朋友,可以微信搜索:xmtxtt,备注:“xttblog”,添加助理微信拉你进群。备注错误不会同意好友申请。再次感谢您的关注!后续有精彩内容会第一时间发给您!原创文章投稿请发送至532009913@qq.com邮箱。商务合作可添加助理微信进行沟通!

本文原文出处:业余草: » 拜托,请别再问我 BIO,NIO,AIO 了!