之前对于四种IO的概念很模糊,今天看了一篇文章,茅塞顿开,所以整理一下。
文章源地址:10分钟看懂, Java NIO 底层原理 - 疯狂创客圈 - 博客园
一、IO(同步阻塞)
用户线程调用操作系统read命令,用户线程阻塞,等待内核接收数据完成(如网卡、磁盘等等,当接收一定数据量之后就算完成),内核将数据从内核缓冲区拷贝到用户线程缓冲区,返回完成,用户线程解阻塞,执行业务逻辑
一个线程对应一个IO操作,当高并发时需要大量的线程,内存等等,高并发不可用
二、NIO(同步非阻塞)
用户线程调用操作系统read命令,如果内核接收数据还未接收完成,就直接返回。
使用一个用户线程轮询多个IO操作,内核未接收完成就返回,继续轮询;直到碰到一个内核数据接收完成的之后,该用户现成进行阻塞,将数据从内核缓冲区拷贝到用户线程缓冲区,然后返回完成,该用户线程解阻塞,通知某个业务线程去执行业务逻辑
该用户线程大量时间在轮询,cpu使用率不高,在实际业务中很少使用这种
三、IO多路复用(javaNIO、异步阻塞)
java中NIO使用的是该种模式,使用操作系统select/epoll(linux会调用epoll)函数获取当前可用IO连接(已经完成了数据接收,并且这个IO已经注册到select可用列表中)。
单个线程A不断轮询select获取可用的IO连接,此时线程A会阻塞,当有任何可用IO之后会返回,此时用户线程B获取了IO连接,调用系统read命令,用户线程B阻塞,将数据从内核缓冲区拷贝到用户线程缓冲区,返回完成,用户线程B解阻塞,执行业务逻辑
优势在于单个线程A可以管理成百上千个IO连接,缺点在于不是真正的异步IO,还是需要用户线程自己去调用read读取数据
四、AIO(异步非阻塞)
用户线程调用操作系统read,不阻塞直接返回,等待系统将接收数据完成,将数据从内核缓冲区复制到用户线程缓冲区之后,向用户线程发出信号,用户线程获取数据,执行业务逻辑。
真正的异步IO,用户线程需要能够接受内核的信号通知,或者内核能够进行用户线程回调的注册等等,需要操作系统的大量支持,目前linux系统对AIO的支持还不够完善,所以常用的还是JavaNIO这种