Java NIO 详解:非阻塞 IO 与多路复用技术
Java NIO(Non-blocking IO,非阻塞 IO)是 JDK 1.4 引入的全新 IO 模型(JDK 1.7 补充 NIO.2),旨在解决传统 IO(BIO)在高并发场景下的性能瓶颈。NIO 基于 “通道(Channel)” 和 “缓冲区(Buffer)” 实现,通过 “多路复用(Selector)” 机制支持单线程处理多个 IO 操作,显著提升系统吞吐量。本文将全面解析 NIO 的核心原理、组件及实践。
NIO 核心概念与优势
阻塞 vs 非阻塞
- 阻塞 IO(BIO):线程调用
read()或write()时会被挂起,直到操作完成才能继续执行。为处理多个客户端,需为每个连接创建独立线程,导致线程资源耗尽(上下文切换开销大)。 - 非阻塞 IO(NIO):线程发起 IO 操作后无需阻塞,可继续处理其他任务;若操作未完成,仅返回 “未就绪” 状态,通过定期轮询或事件通知获取结果。单线程可管理多个 IO 通道,减少线程数量。
NIO 与传统 IO 的核心区别
| 特性 | 传统 IO(BIO) | NIO |
|---|---|---|
| 数据操作单位 | 字节流 / 字符流(Stream) | 缓冲区(Buffer) |
| 传输方向 | 单向(输入流 / 输出流分离) | 双向(通道 Channel 可读写) |
| 阻塞模式 | 阻塞(线程挂起) | 非阻塞(线程可并发处理多任务) |
| 并发处理 | 多线程(一个连接一个线程) | 单线程 / 少线程(多路复用) |
| 核心模型 | 流模型 | 通道 - 缓冲区模型 |
| 适用场景 | 低并发、简单 IO 操作 | 高并发、大流量场景(如网络服务器) |
NIO 核心组件
NIO 的核心由三大组件构成:缓冲区(Buffer)、通道(Channel)、选择器(Selector),三者协同实现非阻塞 IO 操作。
缓冲区(Buffer):数据的容器
Buffer 是一块内存区域,用于存储 IO 操作的数据。所有 NIO 数据读写都必须通过 Buffer 完成(Channel 仅负责传输,不存储数据)。
(1)核心 Buffer 类型
NIO 为每种基本数据类型提供了对应的 Buffer 实现(除 boolean):
| 类型 | 描述 | 示例 |
|---|---|---|
ByteBuffer |
字节缓冲区(最常用) | 网络数据、文件二进制数据 |
CharBuffer |
字符缓冲区 | 文本数据(自动处理编码) |
IntBuffer/LongBuffer等 |
基本类型缓冲区 | 结构化数据(如整数数组) |
(2)Buffer 的核心变量
Buffer 通过三个核心变量控制数据读写,其关系为:0 ≤ mark ≤ position ≤ limit ≤ capacity。