目录
-
- Channel(通道)
- Buffer(缓冲区)
- Selector(选择器)
Java NIO 概述
Java NIO(New I/O)是从 Java 1.4 开始引入的一套新的 I/O API。主要用于 构建高性能、高并发的网络通信程序。
特点
- 面向缓冲区(Buffer)而不是面向流(Stream)
- 支持非阻塞模式(Non-blocking)
- 使用选择器(Selector)实现多路复用
- 更适合高并发服务器端开发
Java BIO vs NIO
特性 | BIO(传统 I/O) | NIO(新 I/O) |
---|---|---|
处理方式 | 同步阻塞 | 同步非阻塞 |
数据处理 | 面向流 | 面向缓冲区 |
多路复用 | 不支持 | 支持 |
并发模型 | 一个线程处理一个连接 | 一个线程处理多个连接 |
适用场景 | 连接数较少,简单 | 高并发、高性能服务器 |
NIO 三大核心组件
1. Channel(通道)
双向的数据传输通道。可以读、写或者同时读写。
常见 Channel 类型:
FileChannel
:用于文件数据的读写SocketChannel
:用于 TCP 网络通信ServerSocketChannel
:用于 TCP 服务端连接监听DatagramChannel
:用于 UDP 数据通信
2. Buffer(缓冲区)
用于存储读取/写入的数据,是 NIO 数据处理的核心。
常见缓冲区类型:
ByteBuffer
CharBuffer
IntBuffer
FloatBuffer
LongBuffer
等
3. Selector(选择器)
用于监听多个 Channel 的事件(如连接、读取、写入),实现 单线程处理多个连接 的能力。
Channel 详解
Channel 是数据的载体,可以与 Buffer 进行读写操作。
// 创建一个 ServerSocketChannel
ServerSocketChannel serverChannel = ServerSocketChannel.open();
serverChannel.bind(new InetSocketAddress(8080));
serverChannel.configureBlocking(false); // 设置非阻塞
Channel 支持以下操作:
read(Buffer buffer)
write(Buffer buffer)
register(Selector selector, int ops)
注册监听事件
Buffer 详解
主要属性:
position
:当前操作位置limit
:限制(最多能操作到哪里)capacity
:容量(最大能装多少数据)
常用方法:
put()
/get()
:写入/读取flip()
:读写模式切换clear()
:清空缓冲区rewind()
:重置 position 为 0
ByteBuffer buffer = ByteBuffer.allocate(1024);
buffer.put("hello".getBytes());
buffer.flip();
byte[] data = new byte[buffer.remaining()];
buffer.get(data);
Selector 详解
Selector 是 Java NIO 提供的 事件轮询器,用于监听多个 Channel 的事件。
Selector selector = Selector.open();
ServerSocketChannel channel = ServerSocketChannel.open();
channel.configureBlocking(false);
channel.register(selector, SelectionKey.OP_ACCEPT);
事件类型:
事件 | 描述 |
---|---|
OP_ACCEPT |
接收连接请求 |
OP_CONNECT |
完成连接 |
OP_READ |
可读取数据 |
OP_WRITE |
可写入数据 |
Selector 处理流程:
- 调用
selector.select()
阻塞等待事件 - 获取
selectedKeys()
- 遍历处理每个事件(如接收连接、读取数据等)
NIO 工作流程图
+-------------+ +------------------+
| Client | | Server |
+-------------+ +------------------+
| |
| TCP Connect |
|----------------------------->|
| |
| |
|<-----------------------------|
| Register Channel to Selector
| |
|---> OP_READ / OP_WRITE ----->|
| |
|<--- selector.select() -------|
| |
|<-------- Read/Write -------->|
示例代码讲解
服务端代码
ServerSocketChannel serverChannel = ServerSocketChannel.open();
serverChannel.configureBlocking(false);
serverChannel.bind(new InetSocketAddress(9999));
Selector selector = Selector.open();
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()) {
SocketChannel client = serverChannel.accept();
client.configureBlocking(false);
client.register(selector, SelectionKey.OP_READ);
}
if (key.isReadable()) {
SocketChannel client = (SocketChannel) key.channel();
ByteBuffer buffer = ByteBuffer.allocate(1024);
int read = client.read(buffer);
if (read > 0) {
buffer.flip();
System.out.println("Received: " + new String(buffer.array(), 0, read));
}
}
}
}
NIO 模型的优缺点
优点
- 更适合构建高并发服务器
- 非阻塞方式提升资源利用率
- 支持多路复用减少线程数量
缺点
- 编程复杂度较高
- 不是真正的异步(NIO 是同步非阻塞)
- 调试和维护成本高于 BIO
NIO 与 Netty 简介
Netty 是基于 Java NIO 封装的高性能网络通信框架。
Netty 优点:
- 封装了复杂的 NIO 使用细节
- 提供异步、事件驱动模型
- 内建线程池、内存管理机制
- 广泛应用于高性能服务器(如 Dubbo、Elasticsearch)
总结
- Java NIO 是面向缓冲区的非阻塞 I/O 模型。
- 三大核心组件:Channel、Buffer、Selector。
- NIO 更适合高并发场景,但开发复杂度较高。
- 实际开发中建议使用 Netty 等高层封装框架。