BIO、NIO、AIO三种IO模型的理解
本文将对三种IO模型做简单的介绍和总结。
1、BIO模型
我们都知道,在做Java网络编程时,服务端在调用accept方法和read方法时是阻塞的,直到有新连接进来或有数据可以读取。在阻塞期间用户线程不能干别的事情,这就是传统的BIO(blocking-io,同步阻塞IO)模型,显而易见,BIO模型在高并发场景下会面临服务端线程数过多浪费系统资源和频繁上下文切换开销问题。
BIO模型图如下:
2、NIO
NIO,no blocking-io,或new io,是同步非阻塞IO。
这里介绍一下什么是同步,什么是阻塞:
同步指的是用户线程从文件(socket也可以看做是文件,Linux一切皆文件)读取数据时整个过程是同步的。
而阻塞指的是,用户线程观察某个文件是否有数据读取时,整个观察过程是阻塞的。
Java NIO是多路复用IO,多路复用IO是非阻塞的,多路复用IO的关键是多路复用器(selector),selector会不停地循环注册在它上面的文件,一旦某个文件有事件发生,再去做相应处理。
因此,对于某个文件的读取而言,就不是阻塞的了,用户线程不会死守在一个文件上面,而是在多个文件上面进行轮询。
那么多路复用器的底层原理是什么呢?这就不得不提到操作系统的select函数。正是有个select函数的支持,多路复用IO才得以实现。
一个用户线程对应一个selector,而一个selector上面可以注册多个文件,但如果文件太多怎么办?比如聊天服务器需要同时支持百万千万的socket连接,即便是轮询,一个线程也吃不消这么多的连接。
此时,就需要发挥多核CPU的优势了。服务端可以开启多个线程,每个线程对应一个selector,那众多的连接数可以被多个线程的selector均分,自然而然压力会降下来。
下面是NIO(多selector)模型图:
3、AIO
AIO是异步IO,在读取数据的整个过程都是异步的,当数据准备好之后,直接由操作系统内核缓冲区将数据复制到用户缓冲区,整个过程不需要用户线程做什么。
但AIO现在还没有广泛应用,现在的大公司服务端采用的都是多路复用IO模型,优点是支持高并发。
4、对比
BIO、NIO、AIO使用场景分析:
BIO适用于连接数小且固定的架构
NIO适用于连接数多且连接比较短(轻操作)的架构,如聊天服务器、弹幕系统、服务器间通讯等,编程比较复杂
AIO适用于连接数多且连接比较长(重操作)的架构,如相册服务器,充分调用os参与并发操作,编程比较复杂