BIO
概念:
BIO 是传统的同步阻塞 I/O,每个请求都需要一个独立的线程来处理。
BIO 适用于连接数较少的场景,因为每个 I/O 操作都会阻塞线程,导致资源消耗较大。
- 每个 I/O 操作(如
read()
、write()
)都会阻塞,直到数据准备好或操作完成。 - 每个客户端连接都需要一个独立的线程来处理(典型的 "一线程一连接" 模型)。
例:传统的socket编程
ServerSocket serverSocket = new ServerSocket(8080);
while (true) {
Socket socket = serverSocket.accept(); // 阻塞等待连接
new Thread(() -> {
try (InputStream in = socket.getInputStream();
OutputStream out = socket.getOutputStream()) {
byte[] buffer = new byte[1024];
int len = in.read(buffer); // 阻塞等待数据
out.write(buffer, 0, len);
} catch (IOException e) {
e.printStackTrace();
}
}).start(); // 每个请求都创建一个新线程处理
}
NIO
概念:
NIO 是同步非阻塞 I/O,使用 Selector
轮询多个通道(Channel),一个线程可以管理多个连接,提高了 I/O 处理效率。
NIO 适用于高并发场景,如聊天服务器、消息推送等。
- 数据读取/写入不会阻塞线程,即使数据未准备好,线程也不会一直等待。
- 一个线程可以同时监听多个通道,提高了资源利用率。
- 通过多路复用(Selector)机制来管理多个通道(Channel),监听它们的状态变化,从而避免传统 BIO 模型中的阻塞问题。
例:
Selector selector = Selector.open();
ServerSocketChannel serverChannel = ServerSocketChannel.open();
serverChannel.configureBlocking(false);
serverChannel.bind(new InetSocketAddress(8080));
serverChannel.register(selector, SelectionKey.OP_ACCEPT);
while (true) {
selector.select(); // 阻塞等待事件
Set<SelectionKey> keys = selector.selectedKeys();
Iterator<SelectionKey> iterator = keys.iterator();
while (iterator.hasNext()) {
SelectionKey key = iterator.next();
iterator.remove();
if (key.isAcceptable()) {
SocketChannel client = serverChannel.accept();
client.configureBlocking(false);
client.register(selector, SelectionKey.OP_READ);
} else if (key.isReadable()) {
SocketChannel client = (SocketChannel) key.channel();
ByteBuffer buffer = ByteBuffer.allocate(1024);
client.read(buffer);
buffer.flip();
client.write(buffer); // 回写数据
}
}
}
NIO它有多种模式:
单线程 Reactor
- 适用于低并发场景,一个线程同时处理连接和 I/O,但容易阻塞。
多线程 Reactor
- Boss 线程(单个):负责监听新连接,并将
SocketChannel
分配给 Worker 线程。 - Worker 线程(多个):每个 Worker 线程维护一个
Selector
,负责多个Channel
的 I/O 读写操作。
Netty 的多线程 Reactor
- BossGroup(NioEventLoopGroup)处理连接请求。
- WorkerGroup(NioEventLoopGroup)管理多个
Selector
,处理 I/O 操作。 - 每个
Worker
线程对应一个Selector
,每个Selector
负责多个Channel
。
AIO
概念:
AIO 是真正的异步 I/O,使用回调方式(CompletionHandler
)处理 I/O 事件,不需要手动轮询 Selector
。
AIO 适用于高并发、I/O 密集型场景,如聊天应用、大量连接的服务器。
- 异步非阻塞:I/O 操作由操作系统完成,完成后触发回调函数(Callback)。
- 线程资源消耗更低,不需要手动轮询
Selector
。
例:
AsynchronousServerSocketChannel server = AsynchronousServerSocketChannel.open();
server.bind(new InetSocketAddress(8080));
server.accept(null, new CompletionHandler<AsynchronousSocketChannel, Void>() {
@Override
public void completed(AsynchronousSocketChannel client, Void attachment) {
server.accept(null, this); // 继续接受新连接
ByteBuffer buffer = ByteBuffer.allocate(1024);
client.read(buffer, buffer, new CompletionHandler<Integer, ByteBuffer>() {
@Override
public void completed(Integer result, ByteBuffer buffer) {
buffer.flip();
client.write(buffer);
}
@Override
public void failed(Throwable exc, ByteBuffer buffer) {
exc.printStackTrace();
}
});
}
@Override
public void failed(Throwable exc, Void attachment) {
exc.printStackTrace();
}
});
Thread.sleep(Long.MAX_VALUE); // 让主线程保持运行
技术选型:
- BIO 适用于小型应用,如简单的 HTTP 服务器、普通 TCP 服务器。
- NIO 适用于高并发场景,如 Web 服务器、聊天应用。
- AIO 适用于超高并发场景,如海量连接的 IM 服务、视频直播系统。
如果你的项目需要支持大量并发连接(几千甚至几万连接),建议使用 NIO 或 AIO,而不是传统的 BIO。