NIO 核心组件(Channel、Buffer、Selector)
NIO(New IO)采用 Channel-Buffer-Selector 模型,比传统 IO 效率更高。
Channel(通道)
特点
- 双向传输,可读可写
- 可异步读写
- 配合 Buffer 使用
主要实现
| Channel 类型 | 说明 |
|---|---|
| FileChannel | 文件通道 |
| SocketChannel | TCP 客户端通道 |
| ServerSocketChannel | TCP 服务端通道 |
| DatagramChannel | UDP 通道 |
FileChannel 示例
Java
// 从文件读取
try (FileChannel channel = new FileInputStream("file.txt").getChannel()) {
ByteBuffer buffer = ByteBuffer.allocate(1024);
int len = channel.read(buffer); // 读取到 buffer
}
// 写入文件
try (FileChannel channel = new FileOutputStream("file.txt").getChannel()) {
ByteBuffer buffer = ByteBuffer.wrap("Hello".getBytes());
channel.write(buffer); // 从 buffer 写入
}
// 文件复制(零拷贝)
try (FileChannel src = new FileInputStream("src.txt").getChannel();
FileChannel dst = new FileOutputStream("dst.txt").getChannel()) {
dst.transferFrom(src, 0, src.size()); // 直接传输
}
Buffer(缓冲区)
核心 Buffer 类型
| Buffer 类型 | 说明 |
|---|---|
| ByteBuffer | 字节缓冲区(最常用) |
| CharBuffer | 字符缓冲区 |
| IntBuffer | 整数缓冲区 |
| LongBuffer | 整数缓冲区 |
| FloatBuffer | 浮点缓冲区 |
| DoubleBuffer | 双精度缓冲区 |
Buffer 核心属性
Java
ByteBuffer buffer = ByteBuffer.allocate(1024);
// capacity:缓冲区容量(1024)
int capacity = buffer.capacity();
// position:当前位置
int position = buffer.position();
// limit:操作边界
int limit = buffer.limit();
Buffer 操作流程
Java
ByteBuffer buffer = ByteBuffer.allocate(1024);
// 1. 写入数据
buffer.put("Hello".getBytes());
// 2. 切换为读模式
buffer.flip(); // position=0, limit=写入长度
// 3. 读取数据
byte[] data = new byte[buffer.limit()];
buffer.get(data);
// 4. 清空缓冲区(准备下次写入)
buffer.clear(); // position=0, limit=capacity
flip() 必须调用:写入后切换为读模式,否则无法正确读取。
Heap Buffer vs Direct Buffer
| 类型 | 创建方式 | 特点 |
|---|---|---|
| Heap Buffer | ByteBuffer.allocate(n) | 在 JVM 堆内存,GC 管理 |
| Direct Buffer | ByteBuffer.allocateDirect(n) | 在本地内存,减少复制,适合大文件 |
Java
// Heap Buffer
ByteBuffer heapBuffer = ByteBuffer.allocate(1024);
// Direct Buffer
ByteBuffer directBuffer = ByteBuffer.allocateDirect(1024);
Selector(选择器)
作用
- 监控多个 Channel 的 IO 事件
- 单线程管理多连接,减少线程开销
- NIO 多路复用的核心
使用示例
Java
Selector selector = Selector.open();
// 注册 Channel 到 Selector
ServerSocketChannel serverChannel = ServerSocketChannel.open();
serverChannel.bind(new InetSocketAddress(8080));
serverChannel.configureBlocking(false); // 非阻塞模式
serverChannel.register(selector, SelectionKey.OP_ACCEPT); // 监听连接
// 事件循环
while (true) {
selector.select(); // 等待事件
Set<SelectionKey> keys = selector.selectedKeys();
Iterator<SelectionKey> iter = keys.iterator();
while (iter.hasNext()) {
SelectionKey key = iter.next();
iter.remove();
if (key.isAcceptable()) {
// 处理连接
}
if (key.isReadable()) {
// 处理读取
}
}
}
SelectionKey 事件类型
| 事件常量 | 说明 |
|---|---|
| OP_ACCEPT | 接收连接 |
| OP_CONNECT | 连接就绪 |
| OP_READ | 读就绪 |
| OP_WRITE | 写就绪 |
要点总结
- Channel:双向通道,可读可写,异步
- Buffer:数据容器,flip() 切换读写模式
- Selector:多路复用器,单线程管理多连接
- FileChannel.transferFrom() 实现零拷贝
- Heap Buffer 在 JVM 堆,Direct Buffer 在本地内存
- Selector 监控 OP_ACCEPT/OP_READ/OP_WRITE 等事件
- NIO 适合高并发网络 IO,传统 IO 适合简单文件操作
📝 发现内容有误?点击此处直接编辑