前言
Java IO 是为了解决 IO 相关操作的,I/O 问题是整个人机交互的核心问题,IO 是机器获取和交换信息的主要渠道。
IO 操作,一般有网络 IO 操作、磁盘 IO 操作等。网络操作相关的类是在 java.net 包下。日常工作中,很多请求—响应的数据交换方式,比如 RPC,都使用了网络 IO。网络 IO 在 移动应用开发、集群中节点通信中都有应用。了解 Java IO,有助于我们应对海量数据导致的 IO 性能瓶颈问题。
Java IO 包按照操作可以分为四大类:
基于字节操作的 I/O 接口:InputStream 和 OutputStream
基于字符操作的 I/O 接口:Writer 和 Reader
基于磁盘操作的 I/O 接口:File
基于网络操作的 I/O 接口:Socket
IO 模型有哪些?
了解 Java IO,先了解 I/O 模型。IO 模型一般分成五大类:
阻塞 IO 模型
非阻塞 IO 模型
IO 复用模型
信号驱动 IO 模型
异步 IO 模型
1. 阻塞 IO 模型
阻塞 IO 模型,以 Linux 系统中 Socket 操作为例,当应用进程空间调用 recvfrom 函数时,其系统调用会一直阻塞直到数据包到达并复制到应用进程的缓存区中或者发送错误时才返回。
阻塞 IO 时序如下图所示:
2. 非阻塞 IO 模型
非阻塞 IO 模型,应用进程调用 recvfrom 函数从应用层到内核的时候,当从缓冲区获取数据时,缓存区没有数据的时候,会直接返回 EWOULDBLOCK 错误,然后一直轮训检查这个状态,看内核是不是数据到来。
3. IO 复用模型
应用进程通过将一个或者多个 fd(file descriptor)传递给 select 或者通过 poll 系统调用,阻塞在 select 操作上,这样 select/poll 可以帮助我们查看多个 fd 是否处于就绪状态,select/poll 顺序扫描 fd 是否就绪,并且支持的 fd 是有限制的,因此 Linux 提供了 epoll 这种基于事件驱动的方式替换了顺序扫描。