Java IO 系列总纲
在Android开发中,不可避免的会接触到IO,抛开系统部分的IO,在应用开发领域,仍然会接触到IO,诸如:
- 文件读写
- 网络通信
或许您在开发中不再直接使用JDK中的API完成IO部分的功能,但仍有必要了解相关知识。
JAVA的IO,通过虚拟机建立在操作系统的IO之上,在梳理JAVA的IO时,可适当了解操作系统部分IO的相关知识,但本系列不会深究。
大纲
本系列中,计划包含以下内容:
- JAVA 经典IO 一篇
- JAVA NIO 1-3篇
- OK-IO 1篇
- Linux系统中的IO(如有必要)
- IO模型概览 本文顺带
下图表现了一个冯诺依曼机的结构:
在操作系统中,IO操作会涉及到 用户空间、内核空间的切换
,以及 内核空间、用户空间之间的数据拷贝
,接下来就常见的IO模型,简单了解下概念和设计理念。
注:不同操作系统在实现时会存在一定差异,不做深究
IO模型
- 阻塞I/O(blocking I/O)
- 非阻塞I/O(non-blocking I/O)
- I/O复用(I/O multiplexing)
- 信号驱动式I/O(signal-driven I/O)
- 异步I/O(asynchronous I/O)
阻塞I/O(blocking I/O)
阻塞IO、BIO、Blocking IO
在
内核IO操作
彻底完成后,才返回用户空间
执行应用的操作。此过程中,用户空间程序的执行状态是阻塞的,程序需等到IO操作彻底完成。
以读为例,示意图如下
非阻塞I/O(non-blocking I/O)
注意,此处不要与 JAVA的nio包
内容混淆
非阻塞IO
相比于BIO,NIO中
数据等待阶段
是非阻塞的,操作系统不会挂起应用。类似于JAVA中使用Future进行非阻塞多线程编程,以读为例,应用
轮询
内核,数据是否完成,数据准备就绪后,发起系统调用获取数据,系统调用的过程中,应用阻塞。
轮询: 应用进程对非阻塞描述符循环发送系统调用,以查看某个操作是否就绪
以读为例,示意图如下
I/O复用(I/O multiplexing)
I/O复用
经典的Reactor设计。进程通过将一个或者多个操作阻塞在
select
阶段,select可以帮我们检测fd(文件操作符)
是否处于就绪状态。如果有数据准备好,就返回可操作的信息,再进行进一步地读写操作
当需要观测的fd很多时,数据准备的占比可能变高,轮询的收益会降低,而多路复用会得到更高的收益。
以读为例,示意图如下
信号驱动式I/O(signal-driven I/O)
信号驱动式I/O
在数据准备阶段,不再阻塞等待,内核准备好数据后,通过信号通知用户空间,用户空间的应用发起系统调用,阻塞获取数据
以读为例,示意图如下
异步I/O(asynchronous I/O)
异步I/O
不同于信号驱动式I/O,在数据等待完成后,进行内核到用户空间的数据拷贝,完成后信号通知应用程序处理数据