1. BIO(Blocking I/O)同步阻塞模型
原理解析: BIO 就像游乐园的传统售票窗口。当调用 Socket.getInputStream().read()
时,JVM 通过 native read()
调用操作系统内核(Linux 的 recvfrom()
)。线程会阻塞在 read()
系统调用上,直到内核从网卡接收到数据并复制到用户空间(源码位置:java.net.SocketInputStream#socketRead
)。
代码示例:
// 传统售票窗口:一个窗口服务一个游客
ServerSocket server = new ServerSocket(8888); // 游乐园开售票窗口
while (true) {
Socket client = server.accept(); // 阻塞!等待游客排队
new Thread(() -> {
BufferedReader in = new BufferedReader(
new InputStreamReader(client.getInputStream())
);
String request = in.readLine(); // 阻塞!等待游客说需求
System.out.println("处理需求:" + request); // 售票员处理票务
}).start();
}
使用场景: 适用于客户端连接数少且稳定的场景(如游乐园团体票预订系统),每个连接需要独立处理逻辑时。
图例:
2. NIO(New I/O)同步非阻塞模型
原理解析: NIO 像游乐园的智能调度中心。核心组件:
Selector:通过
epoll
(Linux)监听多个通道事件Channel:双向数据通道(源码:
sun.nio.ch.EPollSelectorImpl
)Buffer:数据容器(堆外内存减少拷贝)
当调用 selector.select()
时,JVM 通过 epoll_wait
获取就绪事件,避免无效轮询。
代码示例:
Selector selector = Selector.open(); // 调度中心大屏幕
ServerSocketChannel ssc = ServerSocketChannel.open();
ssc.bind(new InetSocketAddress(8888));
ssc.configureBlocking(false); // 非阻塞模式
ssc.register(selector, SelectionKey.OP_ACCEPT); // 监控新游客
while (true) {
if (selector.select(100) == 0) continue; // 智能轮询(不阻塞)
Set<SelectionKey> keys = selector.selectedKeys();
for (SelectionKey key : keys) {
if (key.isAcceptable()) { // 有新游客
SocketChannel sc = ssc.accept();
sc.configureBlocking(false);
sc.register(selector, SelectionKey.OP_READ); // 监控该游客需求
}
if (key.isReadable()) { // 游客有需求
ByteBuffer buf = ByteBuffer.allocate(1024);
((SocketChannel)key.channel()).read(buf); // 非阻塞读取
System.out.println("处理需求:" + new String(buf.array()));
}
}
}
使用场景: 高并发短连接场景(如游乐园实时人流监控系统),1个线程可处理上万连接。
图例:
3. AIO(Asynchronous I/O)异步模型
原理解析: AIO 像游乐园的智能机器人。当调用 AsynchronousSocketChannel.read()
,JVM 提交异步任务给操作系统(Windows 的 IOCP/Linux 的 io_uring)。内核完成数据准备和拷贝后,通过回调通知应用程序(源码:sun.nio.ch.WindowsAsynchronousSocketChannelImpl
)。
代码示例:
AsynchronousServerSocketChannel server =
AsynchronousServerSocketChannel.open().bind(new InetSocketAddress(8888));
// 机器人自动接待游客
server.accept(null, new CompletionHandler<>() {
public void completed(AsynchronousSocketChannel client, Object att) {
ByteBuffer buf = ByteBuffer.allocate(1024);
// 异步读取(不阻塞线程)
client.read(buf, null, new CompletionHandler<>() {
public void completed(Integer bytes, Object att) {
System.out.println("处理需求:" + new String(buf.array()));
}
public void failed(Throwable exc, Object att) {
exc.printStackTrace();
}
});
}
});
Thread.sleep(Long.MAX_VALUE); // 主线程可做其他事
使用场景: 大规模长连接场景(如游乐园智能导览系统),适合文件 I/O 或数据库操作。
图例:
评论区