1. 阻塞IO
阻塞IO模型是最简单的IO模型,也是最常用的IO模型之一。在阻塞IO模型中,当应用程序发起一个IO请求时,如果内核无法立即完成该请求,应用程序线程会被阻塞,直到内核完成该请求。
JAVA代码示例:
Java
import java.io.IOException;
import java.io.InputStream;
public class BlockingIO {
public static void main(String[] args) throws IOException {
InputStream in = System.in;
byte[] bytes = new byte[1024];
int n = in.read(bytes);
System.out.println(new String(bytes, 0, n));
}
}
2. 非阻塞IO
非阻塞IO模型与阻塞IO模型类似,但应用程序线程不会被阻塞。在非阻塞IO模型中,当应用程序发起一个IO请求时,如果内核无法立即完成该请求,应用程序线程可以继续执行其他操作,直到内核完成该请求并通知应用程序。
JAVA代码示例:
Java
import java.io.IOException;
import java.io.InputStream;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
public class NonBlockingIO {
public static void main(String[] args) throws IOException {
ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
serverSocketChannel.configureBlocking(false);
Selector selector = Selector.open();
serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
while (true) {
int n = selector.select();
if (n > 0) {
for (SelectionKey key : selector.selectedKeys()) {
if (key.isAcceptable()) {
// 处理新的连接
} else if (key.isReadable()) {
// 处理可读数据
} else if (key.isWritable()) {
// 处理可写数据
}
}
}
}
}
}
3. IO多路复用
IO多路复用模型允许应用程序监视多个IO句柄,并在一个线程中处理多个IO事件。这可以提高应用程序的效率,因为它不需要为每个IO句柄创建一个单独的线程。
JAVA代码示例:
Java
import java.io.IOException;
import java.io.InputStream;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
public class IOMultiplexing {
public static void main(String[] args) throws IOException {
ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
serverSocketChannel.configureBlocking(false);
Selector selector = Selector.open();
serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
while (true) {
int n = selector.select();
if (n > 0) {
for (SelectionKey key : selector.selectedKeys()) {
if (key.isAcceptable()) {
// 处理新的连接
} else if (key.isReadable()) {
// 处理可读数据
} else if (key.isWritable()) {
// 处理可写数据
}
}
}
}
}
}
4. 信号驱动IO
信号驱动IO模型使用信号来通知应用程序IO事件的发生。这可以提高应用程序的响应速度,因为它不需要轮询IO句柄来检查IO事件。
JAVA代码示例:
Java
import java.io.IOException;
import java.io.InputStream;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
public class SignalDrivenIO {
public static void main(String[] args) throws IOException {
ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
serverSocketChannel.configureBlocking(false);
Selector selector = Selector.open();
serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
while (true) {
int n = selector.select();
if (n > 0) {
for (SelectionKey key : selector.selectedKeys()) {
if (key.isAcceptable()) {
5. 异步IO
异步IO模型允许应用程序在内核完成IO请求之前就继续执行其他操作。这可以提高应用程序的性能,因为它不需要等待IO请求完成。
以下是几种IO模型的比较:
模型 | 优点 | 缺点 |
---|---|---|
阻塞IO | 简单易用 | 应用程序线程会被阻塞 |
非阻塞IO | 应用程序线程不会被阻塞 | 需要应用程序轮询IO句柄 |
IO多路复用 | 可以提高应用程序的效率 | 需要应用程序使用select/poll/epoll等系统调用 |
信号驱动IO | 可以提高应用程序的响应速度 | 需要应用程序处理信号 |
异步IO | 可以提高应用程序的性能 | 需要内核支持异步IO |
选择合适的IO模型取决于应用程序的具体需求。
以下是一些应用场景:
- 对于对性能要求不高的应用程序,可以使用阻塞IO模型。
- 对于对响应速度要求较高的应用程序,可以使用非阻塞IO模型或IO多路复用模型。
- 对于对性能要求较高的应用程序,可以使用异步IO模型。
参考:
- Linux IO模型详解: https://www.cnblogs.com/liushui-sky/p/12917347.html
- 深入聊聊Linux 五种IO模型: 深入聊聊Linux 五种IO模型 - 知乎
- 带你彻底理解Linux五种I/O模型: 带你彻底理解Linux五种I/O模型 | Bigbyto