BIO、NIO、AIO
IO模型
IO模型就是说用什么样的通道进行数据的发送和接收,Java共支持3种网络编程IO模式:BIO,NIO,AIO;
一、BIO(Blocking IO)
同步阻塞模型,一个客户端连接对应一个处理线程
缺点:
1、IO代码里read操作是阻塞操作,如果连接不做数据读写操作会导致线程阻塞,浪费资源;
2、如果线程很多,会导致服务器线程太多,压力太大;
客户端连接服务端,每个连接都需要开启一个线程去处理,若只连接不做数据的收发导致线程阻塞,就会浪费资源;
(1)服务端:new 一个 ServerSocket,调用 socket.accept() 方法,这个方法会阻塞着,等待客户端连接之后就去建立与客户端的连接;
(2)客户端:new 一个 Socket 与 服务器建立连接,向服务端写一条数据;
(3)服务端:socket.InputStream().read() 方法,这个方法会阻塞着, 等待接收到客户端数据之后就读取数据;
二、NIO(Non Blocking IO)
同步非阻塞,服务器实现模式为一个线程可以处理多个请求(连接),客户端发送的连接请求都会注册到多路复用器selector上,多路复用器轮询到连接有IO请求就进行处理。
I/O多路复用,底层一般使用 Linux 的 API(select、poll、epool)来实现,区别如下:
应用场景
NIO方式适用于连接数目多且连接比较短(轻操作) 的架构, 比如聊天服务器, 弹幕系统, 服务器间通讯,编程比较复杂, JDK1.4 开始支持。
NIO 有三大核心组件: Channel(通道), Buffer(缓冲区),Selector(选择器)
(1)channel 类似于流,每个 channel 对应一个 buffer缓冲区,buffer 底层就是个数组;
(2)channel 会注册到 selector 上,由 selector 根据 channel 读写事件的发生将其交由某个空闲的线程处理;
(3)selector 可以对应一个或多个线程;
(4)NIO 的 Buffer 和 channel 都是既可以读也可以写;
NIO相对于BIO非阻塞的体现就在,BIO的后端线程需要阻塞等待客户端写数据(比如read方法),如果客户端不写数据线程就要阻塞。
NIO把等待客户端操作的事情交给了大总管 selector,selector 负责轮询所有已注册的客户端,发现有事件发生了才转交给后端线程处理,后端线程不需要做任何阻塞等待,直接处理客户端事件的数据即可,处理完马上结束,或返回线程池供其他客户端事件继续使用。还有就是 channel 的读写是非阻塞的。
Redis就是典型的NIO线程模型,selector收集所有连接的事件并且转交给后端线程,线程连续执行所有事件命令并将结果写回客户端。
三、AIO(NIO 2.0)
异步非阻塞, 由操作系统完成后回调通知服务端程序启动线程去处理, 一般适用于连接数较多且连接时间较长的应用。