返回
IO系列2-洞悉五种IO模型,构建高效网络应用
后端
2023-11-21 00:20:48
在互联网时代,IO模型是构建高效网络应用的基础。它决定了网络应用程序与操作系统、网络协议之间的交互方式,对系统的性能、并发能力和可扩展性有着至关重要的影响。
IO模型核心概念
同步与异步
同步IO是指在发出IO操作请求后,调用线程会被阻塞,直到操作完成才继续执行。异步IO则相反,IO操作请求发出后,调用线程不会被阻塞,而是继续执行。当IO操作完成时,系统会通过回调或事件通知调用线程。
阻塞与非阻塞
阻塞IO是指IO操作本身会阻塞调用线程。非阻塞IO则相反,IO操作不会阻塞调用线程。即使IO操作尚未完成,调用线程也可以继续执行。
五种IO模型详解
Java中常用的IO模型有五种:
- 同步阻塞IO :最简单的IO模型,IO操作请求发出后调用线程会被阻塞,直到操作完成。
- 同步非阻塞IO :改进的IO模型,IO操作本身不会阻塞调用线程,但调用线程需要不断轮询IO状态,直到操作完成。
- 异步阻塞IO :IO操作请求发出后调用线程会被阻塞,但IO操作本身不会阻塞调用线程。
- 异步非阻塞IO :最先进的IO模型,既不会阻塞IO操作,也不会阻塞调用线程。
- NIO (New IO):一种基于事件驱动的非阻塞IO模型,使用NIO Selector可以同时监听多个IO事件,大幅提升并发处理能力。
代码演示:
// 同步阻塞IO
try (Socket socket = new Socket("127.0.0.1", 80)) {
OutputStream out = socket.getOutputStream();
out.write("GET /index.html HTTP/1.1\r\n".getBytes());
out.flush();
InputStream in = socket.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
String line;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
}
// 同步非阻塞IO
import java.nio.channels.*;
Selector selector = Selector.open();
ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
serverSocketChannel.configureBlocking(false);
serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
while (true) {
int selectedKeys = selector.select();
Set<SelectionKey> selectedKeys = selector.selectedKeys();
for (SelectionKey key : selectedKeys) {
if (key.isAcceptable()) {
SocketChannel socketChannel = ((ServerSocketChannel) key.channel()).accept();
socketChannel.configureBlocking(false);
socketChannel.register(selector, SelectionKey.OP_READ | SelectionKey.OP_WRITE);
} else if (key.isReadable()) {
// 处理读操作
} else if (key.isWritable()) {
// 处理写操作
}
}
selectedKeys.clear();
}
// 异步阻塞IO
import java.nio.channels.*;
AsynchronousServerSocketChannel serverSocketChannel = AsynchronousServerSocketChannel.open();
serverSocketChannel.bind(new InetSocketAddress(80));
serverSocketChannel.accept(null, new CompletionHandler<AsynchronousSocketChannel, Object>() {
@Override
public void completed(AsynchronousSocketChannel result, Object attachment) {
// 处理连接
}
@Override
public void failed(Throwable exc, Object attachment) {
// 处理失败
}
});
// 异步非阻塞IO
import java.nio.channels.*;
CompletionHandler<Void, Object> handler = new CompletionHandler<Void, Object>() {
@Override
public void completed(Void result, Object attachment) {
// 处理写操作完成
}
@Override
public void failed(Throwable exc, Object attachment) {
// 处理写操作失败
}
};
SocketChannel socketChannel = SocketChannel.open();
socketChannel.write(ByteBuffer.wrap("Hello world".getBytes()), null, handler);
// NIO
import java.nio.channels.*;
Selector selector = Selector.open();
ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
serverSocketChannel.configureBlocking(false);
serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
while (true) {
int selectedKeys = selector.select();
Set<SelectionKey> selectedKeys = selector.selectedKeys();
for (SelectionKey key : selectedKeys) {
if (key.isAcceptable()) {
SocketChannel socketChannel = ((ServerSocketChannel) key.channel()).accept();
socketChannel.configureBlocking(false);
socketChannel.register(selector, SelectionKey.OP_READ | SelectionKey.OP_WRITE);
} else if (key.isReadable()) {
// 处理读操作
} else if (key.isWritable()) {
// 处理写操作
}
}
selectedKeys.clear();
}
对比与总结
IO模型 | 同步/异步 | 阻塞/非阻塞 | 优点 | 缺点 |
---|---|---|---|---|
同步阻塞IO | 同步 | 阻塞 | 简单易用 | 低并发性 |
同步非阻塞IO | 同步 | 非阻塞 | 提高并发性 | 需要不断轮询IO状态 |
异步阻塞IO | 异步 | 阻塞 | 提高并发性 | 只能处理有限数量的并发连接 |
异步非阻塞IO | 异步 | 非阻塞 | 最高并发性 | 编程复杂度高 |
NIO | 异步 | 非阻塞 | 极高的并发性 | 编程复杂度高,需要系统支持 |
结语
IO模型是网络编程中的基石,选择合适的IO模型对系统性能和可靠性至关重要。通过理解五种IO模型的原理和优缺点,开发者可以根据应用场景和性能需求,选择最合适的IO模型,构建高效、可靠的网络应用。