IO 模型有哪些?谈谈你理解的 NIO,它和 BIO、AIO 的区别,Reactor 模型?¶
一、五种 IO 模型¶
Unix 提出的五种:
- 阻塞 IO(BIO):recvfrom 一直等数据。
- 非阻塞 IO(NIO):recvfrom 立即返回 EWOULDBLOCK,循环问。
- IO 多路复用:select/poll/epoll 同时等多个 fd。
- 信号驱动 IO:内核通知可以 IO。
- 异步 IO(AIO):内核把数据拷贝完再通知。
二、BIO vs NIO vs AIO¶
| BIO | NIO | AIO | |
|---|---|---|---|
| 模式 | 同步阻塞 | 同步非阻塞 | 异步非阻塞 |
| 核心 | Stream | Channel + Buffer + Selector | Future/Callback |
| 适用 | 连接少 | 连接多 | 连接多、操作重 |
BIO¶
一个连接一个线程,连接不做事也占线程。
NIO(Java NIO)¶
- 三要素:Channel、Buffer、Selector。
- 一个线程通过 Selector 管理多个 Channel。
- 同步非阻塞:线程发起 read,数据没准备好就返回,线程去做别的事。
AIO¶
- 真正异步:发起 read,内核准备好数据并拷贝到用户缓冲区后,回调通知。
- Linux 上 AIO 实现不完善,Windows 用得好。
三、Reactor 模型¶
NIO 的经典设计模式:
单 Reactor 单线程¶
一个线程跑所有事件。简单,但 CPU 密集场景是瓶颈。
单 Reactor 多线程¶
读解码在主线程,业务处理丢到线程池。
主从 Reactor 多线程(Netty)¶
- 主 Reactor:只 accept 连接。
- 从 Reactor:处理已建立连接的读写。
- 业务线程池:处理业务。
Netty 就是这种模型。
四、Java NIO 三要素¶
Channel¶
双向通道,可读可写。常见:SocketChannel、ServerSocketChannel、FileChannel。
Buffer¶
数据容器,有 position/limit/capacity 三个指针。
Selector¶
一个线程监听多个 Channel 的事件(connect/read/write/accept)。
五、零拷贝¶
NIO 的 FileChannel.transferTo() 用 sendfile 系统调用,数据直接从文件到 Socket,不经过用户态。
高频追问
- 为什么 FileChannel 不能非阻塞?文件 IO 没有"等待连接"的概念。
- epoll vs select:epoll 没有 fd 上限,回调机制,适合大规模连接。