何为I/O流
从字面I(Input)/O(output),既输入/输出,从计算机的结构来看,可分为五大部分:运算器、控制器、存储器、输入设备、输出设备,如图所示:
咱重点看输入设备和输出设备,输入设备向计算机输入数据,输出设备是计算器经过处理后输出的数据。
然后咱们通过应用程序的角度去解读I/O:为了保证系统的安全性和稳定性,一个进程可以分为用户空间和内核空间,用户空间主要运行的是应用程序,内核空间主要进行系统级别的操作,所以从应用程序角度去看,应用程序只是对操作系统发起了I/O调用(系统调用),操作系统负责的内核进行具体的I/O操作,当应用系统发起I/O调用后,会经历两步:
1、内核等待I/O设备准备好数据,
2、内核将数据从内核空间拷贝到用户空间。
Java中常见的3种I/O模型:
通过上面可以知道应用程序是如何从内核获取的数据,但获取数据有不同的方式,以下就是重点说一下常见的I/O模型。
BIO(Blocking I/O)
BIO属于同步阻塞I/O模型:
该模型特点是应用程序发起I/O调用后,会一直堵塞,直到内核把数据拷贝到用户空间。
这种连接模式在客户端链接少的时候是没有问题的,但当面对数十万乃至上百万的时候,传统的BIO模式就无能为力了,所以我们需要一个更加高效I/O处理模型来应对更高的并发量。
NIO(Non-blocking/New I/O )
该模型是Java 1.4引用的,他支持面向缓冲,基于通道的I/O的操作方法,因为在Java的NIO可以看做多路复用模型,所以有很多人也称这种模型叫同步非阻塞I/O模型。
咱先看看同步非阻塞的工作原理:
在同步非阻塞模型中,应用程序会一直发起read调用,等待数据从内核空间拷贝到用户空间的这段时间,线程依旧是堵塞的,直到内核数据拷贝到用户空间。
这点相比同步阻塞模型来说,通过进行轮询查询有了很大的改善,但是这种模型同样有一个致命的缺点:应用系统不断的进行I/O系统调用轮询查询是否准备好的过程是非常消耗CPU资源的。
这个时候发现同步非阻塞模型也满足不了需求时,于是I/O多路复用模型就诞生了
在多路复用I/O模式中,会在线程调用时,首先发起select调用,查询内核数据是否准备就绪,等内核数据整理好之后,再通过read调用,但要注意read调用过程还是阻塞的。
AIO(Asynchronous I/O)
AIO也就是NIO2,属于Java7中新引进的,采用的是异步IO模型,既异步IO是基于时间和回调机制实现的,也就是说read请求之后会直接返回,不会堵塞在现场,等内核空间将数据处理好之后,操作系统会通知线程进行后续的操作,如图所示。
最后一张图来总结Java中的BIO、NIO、AIO: