NIO,是一个比较高级的知识点。平时的代码开发中,我们一般很少直接使用NIO相关知识点。但是,其却是各种通信框架的基础知识。如Netty、Mina等,就是基于NIO来进行开发的。
IO,我们知道,是Input/Output,输入输出,可以是网络流的IO,也可以是文件的IO。通常这是一种BIO。
到这里,我们引入了BIO、NIO,如果了解的多一点的话还有AIO。那么它们之间有什么关系呢?
本文将简单介绍上述三者之间的区别,并且拆分NIO的知识点,后续博客会对NIO的各个知识点进行更详细的说明。
1.同步异步、阻塞非阻塞状态 1.1 同步与异步经常会听到同步请求,异步请求。
区分一个请求是同步还是异步的话,主要看请求在调用过来时候,是等待直到执行结果完成,还是及时返回结果,后续通过异步通知或回调的方式来告诉调用方。
同步请求:调用方发起调用后,会一直等待,直到被调用方返回一个响应结果为止
异步请求:调用方发起调用后,被调用方立即返回一个响应,后续被调用方通过异步通知或者回调的方式来告知调用方其结果。
1.2 阻塞与非阻塞阻塞与非阻塞主要是关注程序在等待执行结果时的状态
阻塞:当结果返回之前,线程会被挂起(BLOCK状态)
非阻塞:当结果返回之前,线程不会被挂起(非BLOCK状态)
有了上述基础知识后,我们再来分析下BIO NIO 与AIO的不同之处。
2.操作系统视角下的BIO、NIO和AIO 2.1 BIO 即Blocking IO(阻塞IO),操作系统下BIO整个过程如下所示:
当应用程序发起系统调用时,1)操作系统首先需要先将数据拷贝到系统内核缓冲区,2)然后再将内核缓冲区的数据拷贝到应用程序的进程空间(JVM就是堆内存等)
在BIO的情况下,应用程序发起系统调用后,会一直等待操作系统执行完上述的数据拷贝之后,才结束调用。(此时该请求线程会被BLOCK)
2.2 NIO即None-Blocking IO,操作系统视图下NIO调用过程如下:
相比较BIO而言,发起系统调用后,应用程序线程不是一直在阻塞等待数据返回,而是在不停的轮询查询操作系统是否将数据准备好,当操作系统准备好数据之后,后续的从内核空间拷贝数据到用户空间的过程与BIO相同。
所以,BIO是上述两个阶段都是阻塞的,而NIO第一个阶段非阻塞,第二个阶段阻塞。
另:有关于非阻塞IO,还有一个非常重要的概念,叫做多路复用模型。该模型共包含三种解决方案:select、poll、epoll。应用程序使用这些IO函数同时监听多个IO通道的状态变更,可以更好的支持更大量级的连接。
有关于多路复用模型,会在下一篇文章中单独说明。
2.3 AIO
即Asynchronous IO,异步IO在操作系统视角下的调用过程如下:
应用程序线程发起一个系统调用后,会立即返回,调用事件注册到操作系统上,操作系统准备完成数据并将数据拷贝到用户空间后,会通知应用程序数据已经可用。
在上述两个过程中,AIO均为非阻塞状态
需要说明的是:Java中的BIO NIO和AIO是java对操作系统的各种IO模型的封装。
IO类型一阶段(数据拷贝至操作系统内核空间)二阶段(内核空间数据拷贝至应用程序)BIO同步阻塞同步阻塞NIO同步非阻塞同步阻塞AIO异步非阻塞异步非阻塞 总结:实际写一个完整的系列还是蛮困难的,无论写的多还是写的少都比较困难,笔者没有采取先写一个完整示例然后再将示例的知识点拆分的方式,而是反其道而行,先讲解拆分后的知识点,然后最终用一个真实的示例来将知识点串起来。
整个NIO系列本质上也是其他系列的基础篇章,后续还会有Mycat系列、Netty系列等等。这些高级中间件其实底层也是使用的NIO相关知识。
工欲善其事必先利其器,让我们一起遨游在NIO的海洋里吧。