一、IO模型概述
Java中的IO模型主要分为BIO(同步阻塞IO)、NIO(同步非阻塞IO)和AIO(异步非阻塞IO)三种。它们分别适用于不同的业务场景,理解其核心机制对高性能网络编程至关重要。
二、BIO:同步阻塞IO
1. 核心机制
BIO基于“一连接一线程”模型,服务端通过ServerSocket
监听端口,客户端通过Socket
发起连接。当服务端调用accept()
或read()
时,线程会阻塞直至数据就绪。
2. 代码示例
服务端代码片段:
ServerSocket serverSocket = new ServerSocket(9999);
Socket socket = serverSocket.accept(); // 阻塞
InputStream is = socket.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(is));
String msg = br.readLine(); // 阻塞直至数据到达
客户端代码片段:
Socket socket = new Socket("127.0.0.1", 9999);
PrintStream ps = new PrintStream(socket.getOutputStream());
ps.println("Hello BIO!");
ps.flush();
3. 优缺点分析
- 优点:编程简单,适合低并发场景。
- 缺点:线程资源消耗大,高并发时易导致线程栈溢出。
三、NIO:同步非阻塞IO
1. 核心组件
NIO的三大核心为通道(Channel)、缓冲区(Buffer)和选择器(Selector):
- Channel:双向通信管道,替代BIO的单向流。
- Buffer:数据存储容器,支持高效读写。
- Selector:多路复用器,单线程管理多个Channel的事件。
2. 工作机制
通过Selector.select()
监听事件,实现非阻塞IO。服务端仅需一个线程即可处理多个连接请求,显著提升性能。
服务端代码片段:
ServerSocketChannel serverChannel = ServerSocketChannel.open();
serverChannel.configureBlocking(false);
serverChannel.bind(new InetSocketAddress(9090));
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();if (key.isAcceptable()) {// 处理连接事件} else if (key.isReadable()) {// 处理读事件}iter.remove();}
}
3. Buffer操作流程
- 写入数据:
buffer.put(data)
- 切换为读模式:
buffer.flip()
- 读取数据:
buffer.get()
- 清空缓冲区:
buffer.clear()
示例:
ByteBuffer buffer = ByteBuffer.allocate(1024);
buffer.put("Hello NIO".getBytes());
buffer.flip();
while (buffer.hasRemaining()) {System.out.print((char) buffer.get());
}
4. 适用场景
适用于高并发短连接场景(如聊天服务器)。
四、AIO:异步非阻塞IO
1. 核心机制
AIO基于操作系统级别的异步通知机制,IO操作由OS完成后回调通知应用,无需线程阻塞。核心类包括AsynchronousServerSocketChannel
和CompletionHandler
。
2. 代码示例
AsynchronousServerSocketChannel server = AsynchronousServerSocketChannel.open();
server.bind(new InetSocketAddress(9090));
server.accept(null, new CompletionHandler<AsynchronousSocketChannel, Void>() {@Overridepublic void completed(AsynchronousSocketChannel client, Void attachment) {ByteBuffer buffer = ByteBuffer.allocate(1024);client.read(buffer, buffer, new CompletionHandler<Integer, ByteBuffer>() {@Overridepublic void completed(Integer result, ByteBuffer buf) {System.out.println("收到数据:" + new String(buf.array()));}});}
});
3. 适用场景
适合长连接、重操作场景(如文件服务器),但实际应用中因编程复杂度和兼容性问题,使用较少。
五、三种IO模型对比
特性 | BIO | NIO | AIO |
---|---|---|---|
阻塞性 | 同步阻塞 | 同步非阻塞 | 异步非阻塞 |
线程模型 | 一连接一线程 | 单线程多路复用 | 回调通知机制 |
适用场景 | 低并发、简单业务 | 高并发短连接(如IM系统) | 高并发长连接(如文件传输) |
编程复杂度 | 简单 | 复杂 | 复杂 |
JDK支持 | JDK1.0 | JDK1.4 | JDK1.7 |
六、总结
- BIO:适合快速原型开发,但需避免用于高并发场景。
- NIO:Netty等框架的底层实现,推荐用于高性能服务器开发。
- AIO:在特定场景下性能优异,但需评估框架支持度。