一.首先什么是IO模型:
就是用什么样的方式进行数据的接收和发送,和很大程度上决定了程序通信的性能。
二.为什么要有不同得IO模型,解决什么问题?
首先在发送数据时,举例从应用A发送数据到应用B,首先应用A会先将数据发送到TCP中的缓冲区,然后再发送到应用B所在服务器的缓冲区,然后B应用从缓冲区中读取数据。
这就涉及到一个问题,因为我们发送消息是间隔的,那么当应用B去缓冲区中拿数据时,如果缓冲区中无数据,是等待接收数据呢?还是直接返回。其实就涉及到阻塞和非阻塞的效果。
Java中的IO模型主要有三种BIO和NIO.AIO.其实主要是同步阻塞,同步不阻塞,异步不阻塞的区别。
这里的同步,异步,阻塞,非阻塞解释如下:
- 同步:当触发读写请求后,等待数据就绪并将数据从内核读取到用户空间,直到返回数据.
简单来说就是应用发送完指令要参与整个过程,直到返回数据 - 异步:当触发读写请求后(这里不是去缓冲区读写,仅仅告诉内核我想去读取数据),直接返回,内核帮助你完成整个操作后,帮你将数据从内核复制到应用空间,再通知你.
简单来说就是应用发送完指令不再参与整个过程,直接返回等待通知. - 阻塞:试图对缓冲区进行读写时,当前不可读或者不可写(内核数据没有准备好的情况下),程序进行等待,直到可以操作。
- 非阻塞:试图对缓冲区进行读写时,当前不可读或者不可写,读取函数马上返回。
三.各种优缺点:
实现方式:服务器每收到一个请求,就会创建一个线程去读取对应数据,同时线程也不知道什么时候会有数据,所以会阻塞等待。这样如果一下子收到成千上万的请求,就会创建成千上万个线程去读取数据,非常浪费资源。只适用于连接数少且固定的架构.
实现方式:有专门的线程去轮询完成对数据状态询问的操作(当前是否有数据可读取),当有数据准备就绪后分配对应的线程去读取数据,这就相比前一种就可以节省大量的线程资源出来。
适用于连接数多且连接较短的架构.
应用程序将具体操作告诉内核(比如说我要读一个数据),此时应用程序就直接返回了,当内核完成操作后通知应用程序,适用于连接数多且连接较长的架构.
参考博客:
https://zhuanlan.zhihu.com/p/115912936