这部分的东西在网络编程经常能看到,不过在所有 IO 处理中都是类似的。
IO 请求的两个阶段 :
等待资源阶段 : IO 请求一般需要请求特殊的资源(如磁盘、 RAM 、文件),当资源被上一个使用者使用没有被释放时, IO 请求就会被阻塞,直到能够使用这个资源。
使用资源阶段 :真正进行数据接收和发生。
举例说就是排队 和服务。
在等待数据 阶段, IO 分为阻塞 IO 和非阻塞 IO 。
阻塞 IO :资源不可用时, IO 请求一直阻塞,直到反馈结果(有数据或超时)。
非阻塞 IO :资源不可用时, IO 请求离开返回,返回数据标识资源不可用
在使用资源 阶段, IO 分为同步 IO 和异步 IO 。
同步 IO :应用阻塞在发送或接收数据的状态,直到数据成功传输或返回失败。
异步 IO :应用发送或接收数据后立刻返回,数据写入 OS 缓存,由 OS 完成数据发送或接收,并返回成功或失败的信息给应用。
按照 Unix 的 5 个 IO 模型划分
- 阻塞 IO
- 非阻塞 IO
- IO 复用
- 信号驱动的 IO
- 异步 IO
从性能上看,异步 IO 的性能无疑是最好的。
各种 IO 的特点
- 阻塞IO :使用简单,但随之而来的问题就是会形成阻塞,需要独立线程配合,而这些线程在大多数时候都是没有进行运算的。 Java 的 BIO 使用这种方式,问题带来的问题很明显,一个 Socket 需要一个独立的线程,因此,会造成线程膨胀。
- 非阻塞IO :采用轮询方式,不会形成线程的阻塞。 Java 的 NIO 使用这种方式,对比 BIO 的优势很明显,可以使用一个线程进行所有 Socket 的监听( select )。大大减少了线程数。
- 同步IO :同步 IO 保证一个 IO 操作结束之后才会返回,因此同步 IO 效率会低一些,但是对应用来说,编程方式会简单。 Java 的 BIO 和 NIO 都是使用这种方式进行数据处理。
- 异步IO :由于异步 IO 请求只是写入了缓存,从缓存到硬盘是否成功不可知,因此异步 IO 相当于把一个IO 拆成了两部分,一是发起请求,二是获取处理结果。因此,对应用来说增加了复杂性。但是异步 IO 的性能是所有很好的,而且异步的思想贯穿了 IT 系统放放面面。