1 BIO
同步阻塞。服务端采用一个连接一个线程方式,客户端有连接请求时,服务器随即启动一个线程进行处理。
JDK1.4前,采用BIO方式建立网络连接,服务端启动ServerSocket,客户端启动Socket连接服务端进行通信,默认情况下,服务端对每个请求建立一个线程,客户端发起请求后,遍历服务端是否有线程响应,没有响应则一致等待,要么超时,要么等到线程资源,响应数据。
BIO结构如下图所示:
(1)每个线程维护一个Socket连接,服务器连接数有限,客户端连接数暴增时,容易压垮服务器;
(2)使用流读取数据,流是阻塞的,没有可读或可写数据时,线程等待,造成资源浪费。
2 NIO
同步非阻塞。服务端采用一个请求一个线程方式,客户端发送的连接请求都会注册到多路复用器上,多路复用器轮询连接有I/O请求时才启动一个线程进行处理。
NIO基于事件驱动思想。主要是为了提高服务并发能力。
多个Socket连接共用一个线程,提高线程资源利用率,提高服务的并发能力。
当Socket连接有数据流可写或可读时,操作系统会通知应用程序处理,
应用将流读取到缓冲区或写入操作系统,这里,是有效的请求对应一个处理线程。
NIO结构如下图所示:
(1)线程中包含一个Selector对象,即多路复用器,可以实现一个单独线程中处理多个通道,从而减少线程创建数量。线程中的多路复用器进行轮询时,发现连接上有请求时,才开启一个线程进行处理,即一个请求一个线程处理。
(2)远程连接对应一个SocketChannel,数据的读写通过缓冲(Buffer)均在同一个通道(Channel)中完成,并且数据的读写是非阻塞的。
(3)通道创建后需要注册到Selector中,同时需要为该通道注册感兴趣事件(客户端连接服务端事件、服务端接收客户端事件、读事件、写事件),Selector线程需要采用轮询的方式调用Selector的select函数,直到,所有注册通道中有感兴趣的事件发生,则返回,否则,一直阻塞。然后,循环处理所有就绪的感兴趣事件。
3 AIO
异步非阻塞。服务端采用一个有效请求一个线程方式,客户端的I/O请求,均有操作系统先完成,再通知服务器应用程序启动线程处理。
4 小结
- BIO:同步阻塞。服务端:一个连接一个线程,客户端有连接请求时,服务器随即启动一个线程进行处理。
- NIO:同步非阻塞。服务端:一个请求一个线程,客户端发送的连接请求都会注册到多路复用器上,多路复用器轮询连接有I/O请求时才启动一个线程进行处理。
- AIO:异步非阻塞。服务端:一个有效请求一个线程,客户端的I/O请求,均有操作系统先完成,再通知服务器应用程序启动线程处理。