理解和对比BIO、NIO、AIO的特性

示例代码:https://gitee.com/shiker/Stream,文章和代码更配哦

同步阻塞式--BIO

一个客户端(连接)对应一个线程,只有一个服务线程为每个连接分配处理线程

缺点:缺乏弹性伸缩能力,服务端与客户端并发访问数呈1:1的正比关系,并发访问量过大,系统会产生线程堆栈溢出,创建新线程失败的问题,导致宕机或者僵死,不能对外提供服务。

核心代码实例:

TimeServer

TimeServerHandler:

TimeClient:

执行结果

伪异步IO

 利用线程池和任务队列实现,将客户端的socket封装成一个task,即是通过线程池分配给每个连接当前为工作的线程。但是还是只有一个服务线程为连接分配线程池中的线程。

弊端:服务端处理读操作缓慢时会导致多个输入流阻塞,阻塞队列积满后后入列操作无法进行,最终导致大量连接超时。

核心代码:

server

程序执行结果:


非阻塞--NIO

1.缓冲区:有字节缓冲区、字符缓冲区、整型缓冲区等,通常是一个字节数组,提供了对数据的结构化访问以及维护读写位置等信息。

2.通道:channel是一个通道,网络数据通过channel读取和写入。通道与流的不同在于通道是双向的,流只是一个方向上移动。通道可以用于读、写或者同时读写。

channel分为两大类,用于网络读写的selectableChannel和用于文件操作的FileChannel。

3.多路复用器:提供了选择已经就绪的任务的能力,通过不断轮询注册在其上的channel,获取就绪状态的channel。一个多路复用器可以轮询多个channel,没有最大连接句柄的限制。

优点:客户端发起的连接操作是异步的,不需要被同步阻塞;socketchannel的读写操作也是异步的,不需要等待这个链路可用。连接数量不受限制。

示例执行结果

异步非阻塞--AIO

NIO2.0引入新的概念,提供了异步文件通道,和异步套接字通道的实现。提供了两种方式获取操作结果。

1. 通过Future类表示异步操作的结果

2. 在执行异步操作的时候传入一个channels。

CompletionHandler接口的实现类作为操作完成的回调。NIO2.0对应于事件驱动IO,不需要多路复用器进行轮询操作即可实现异步读写。


执行结果:

总结:

同步阻塞IO

伪异步IO

非阻塞IO

异步IO

客户端:服务端

1:1

M:N(M>N)

M:1(一个IO线程处理多个了客户端连接)

M:0(不需要启动额外的IO线程,被动回调)

IO类型

同步阻塞

同步阻塞

同步非阻塞

异步非阻塞

API使用难度

简单

简单

非常复杂

复杂

调试难度

简单

简单

复杂

复杂

可靠性

相当差

吞吐量

向当低



猜你喜欢

转载自blog.csdn.net/yinweicheng/article/details/80586653