NIO概述
Java NIO 是 Java 1.4 引入的新 IO API。这里的 NIO 最初通常理解为 New IO,后来也常被理解为 Non-blocking IO。它和传统 IO 最大的差异是:传统 IO 面向流,NIO 面向缓冲区和通道,并支持非阻塞 IO 和多路复用。
# 1. 传统 IO 的特点
传统 IO 以流为中心:
InputStream / OutputStream
Reader / Writer
特点:
- 面向流,数据顺序读写。
- API 简单,适合文件和简单网络通信。
- Socket IO 默认阻塞。
- 一个阻塞连接通常需要一个线程处理。
对于连接数不高、逻辑简单的系统,传统 IO 足够好。但面对大量网络连接时,线程数量、上下文切换和内存占用会成为瓶颈。
# 2. NIO 的核心组件
NIO 有三个核心概念:
Buffer:缓冲区,数据读写的容器。Channel:通道,连接数据源和目标。Selector:选择器,一个线程监听多个通道的事件。
数据源 <-> Channel <-> Buffer <-> 程序
多个 Channel -> Selector -> 一个线程处理多个事件
# 3. Buffer
传统 IO 中,程序直接从流中读取数据。NIO 中,数据先进入 Buffer,程序再从 Buffer 中读取。
常见 Buffer:
ByteBufferCharBufferIntBufferLongBufferMappedByteBuffer
网络和文件 IO 中最常用的是 ByteBuffer。
# 4. Channel
Channel 类似通道,负责和底层资源交互。它可以从通道读取数据到 Buffer,也可以把 Buffer 中的数据写入通道。
常见 Channel:
FileChannel:文件通道。SocketChannel:客户端 Socket 通道。ServerSocketChannel:服务端 Socket 通道。DatagramChannel:UDP 通道。
和传统流相比,Channel 通常是双向的,既可以读也可以写。
# 5. Selector
Selector 是 NIO 网络编程的关键。它可以让一个线程管理多个 Channel。
常见事件:
OP_ACCEPT:接收连接。OP_CONNECT:连接完成。OP_READ:可读。OP_WRITE:可写。
这就是 Reactor 模式的基础,也是 Netty 等高性能网络框架的重要底层思想。
# 6. NIO 适合什么场景
适合:
- 高并发网络服务。
- 长连接系统。
- 网关、代理、消息中间件。
- 需要减少线程数量的 Socket 服务。
- 文件高性能读写。
- 零拷贝、内存映射等高级文件处理。
不一定适合:
- 简单文件读取。
- 简单命令行工具。
- 连接数很少、业务逻辑简单的系统。
简单场景中过度使用 NIO 会增加代码复杂度。
# 7. NIO 和 NIO.2
Java 7 引入了 NIO.2,主要增强文件系统 API 和异步通道:
PathFilesFileSystemWatchServiceAsynchronousFileChannelAsynchronousSocketChannel
日常文件操作中,我们经常用到的 Files、Path 属于 NIO.2。
# 专家实践清单
| 问题 | NIO 的答案 | 工程关注点 |
|---|---|---|
| 数据放哪里 | Buffer | 状态切换、直接内存 |
| 数据从哪来 | Channel | 非阻塞、半包读写 |
| 多连接怎么等 | Selector | 事件循环、空轮询 |
| 文件怎么高效处理 | FileChannel | 位置读写、零拷贝 |
| 路径怎么表达 | Path / Files | 异常和文件系统能力 |
NIO 学习路径:
Buffer 状态机
▼
Channel 读写模型
▼
Selector 事件模型
▼
Reactor / Netty
▼
零拷贝、内存映射、性能排查
# Tips 快问快答
Q:NIO 的三个核心组件是什么? A:Buffer、Channel、Selector。
Q:NIO 一定是非阻塞吗? A:不是。NIO 包含多种能力,Channel 可以配置为阻塞或非阻塞。
Q:Buffer 的作用是什么? A:作为读写数据的内存容器。
Q:Channel 和 Stream 最大区别是什么? A:Channel 通常双向并配合 Buffer,Stream 更像单向顺序流。
Q:Selector 解决什么问题? A:用少量线程监听多个 Channel 的就绪事件。
Q:NIO.2 包含什么?
A:Path、Files、异步 Channel、文件属性等现代文件 API。
Q:什么时候不需要 NIO? A:普通小文件读写、连接数很少、团队无需维护复杂事件模型时。
Q:学习 NIO 最大的坑是什么? A:只记 API,不理解 Buffer 状态机和事件驱动模型。
# 8. 总结
传统 IO 更简单,适合普通文件和低并发场景。NIO 更复杂,但提供了缓冲区、通道、选择器、多路复用、内存映射、零拷贝等能力,是理解高性能 Java 网络和文件处理的重要基础。