BIO、NIO 和 AIO 是三种不同的 I/O 模型,它们分别代表了不同的 I/O 处理方式。
-
BIO (Blocking I/O) - 阻塞 I/O
-
NIO (Non-blocking I/O) - 非阻塞 I/O
-
AIO (Asynchronous I/O) - 异步 I/O
BIO(Blocking I/O)
BIO 模型是 Java 最传统的 I/O 模型,基于流的同步阻塞 I/O 操作。每个连接都会占用一个线程,当进行 I/O 操作时,线程会被阻塞,直到操作完成。适用于连接数较少且固定的架构,例如传统的 C/S 架构,因其实现简单、编程直观。
特点:
-
同步阻塞:每个 I/O 操作都会阻塞当前线程,直到操作完成。
-
线程占用:每个连接需要一个独立的线程,线程资源消耗较大。
-
实现简单:代码实现相对简单,易于理解和编写。
import java.io.*;
import java.net.*;
public class BIOServer {
public static void main(String[] args) throws IOException {
ServerSocket serverSocket = new ServerSocket(8080);
while (true) {
Socket socket = serverSocket.accept();
new Thread(() -> {
try {
BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
PrintWriter writer = new PrintWriter(socket.getOutputStream(), true);
String message;
while ((message = reader.readLine()) != null) {
writer.println(message);
}
} catch (IOException e) {
e.printStackTrace();
}
}).start();
}
}
}
NIO(Non-blocking I/O)
NIO 是 Java 1.4 引入的新 I/O API,基于通道(Channel)和缓冲区(Buffer)的非阻塞 I/O 操作。它支持非阻塞模式,允许一个线程管理多个连接,实现了多路复用(Selector)。适用于连接数较多且连接较短的架构,如高并发的服务器端应用。
特点:
-
非阻塞:I/O 操作不会阻塞线程,线程可以在等待数据时执行其他任务。
-
多路复用:通过 Selector 可以管理多个 Channel,提高了资源利用率。
-
高性能:适用于高并发场景,减少线程开销和上下文切换。
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
public class NIOServer {
public static void main(String[] args) throws IOException {
Selector selector = Selector.open();
ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
serverSocketChannel.bind(new InetSocketAddress(8080));
serverSocketChannel.configureBlocking(false);
serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
while (true) {
selector.select();
Iterator<SelectionKey> keys = selector.selectedKeys().iterator();
while (keys.hasNext()) {
SelectionKey key = keys.next();
keys.remove();
if (key.isAcceptable()) {
ServerSocketChannel serverChannel = (ServerSocketChannel) key.channel();
SocketChannel socketChannel = serverChannel.accept();
socketChannel.configureBlocking(false);
socketChannel.register(selector, SelectionKey.OP_READ);
} else if (key.isReadable()) {
SocketChannel socketChannel = (SocketChannel) key.channel();
ByteBuffer buffer = ByteBuffer.allocate(1024);
int bytesRead = socketChannel.read(buffer);
if (bytesRead > 0) {
buffer.flip();
socketChannel.write(buffer);
} else if (bytesRead == -1) {
socketChannel.close();
}
}
}
}
}
}
AIO(Asynchronous I/O)
AIO 是 Java 7 引入的异步 I/O API,基于异步通道(AsynchronousChannel)和异步回调机制。AIO 操作是非阻塞和异步的,即操作立即返回,结果通过回调函数处理。适用于连接数较多且连接时间较长的架构,如高并发的服务器端应用。
特点:
-
异步非阻塞:I/O 操作是异步的,通过回调处理结果,不阻塞线程。
-
回调机制:通过回调函数处理 I/O 操作结果,提高了程序的灵活性。
-
发起异步 I/O 操作:程序发起一个异步 I/O 请求,并提供一个回调函数。
-
继续执行其他任务:程序无需等待 I/O 操作完成,而是立即返回,继续执行其他任务。
-
I/O 操作完成:当 I/O 操作完成后,系统会调用之前提供的回调函数,传递结果或状态信息。
-
处理结果:回调函数负责处理 I/O 操作的结果,如读取数据或处理错误。
-
高性能:适用于高并发、高吞吐量的场景。
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.AsynchronousServerSocketChannel;
import java.nio.channels.AsynchronousSocketChannel;
import java.nio.channels.CompletionHandler;
public class AIOServer {
public static void main(String[] args) throws IOException {
AsynchronousServerSocketChannel serverChannel = AsynchronousServerSocketChannel.open();
serverChannel.bind(new InetSocketAddress(8080));
serverChannel.accept(null, new CompletionHandler<AsynchronousSocketChannel, Void>() {
@Override
public void completed(AsynchronousSocketChannel result, Void attachment) {
serverChannel.accept(null, this);
ByteBuffer buffer = ByteBuffer.allocate(1024);
result.read(buffer, buffer, new CompletionHandler<Integer, ByteBuffer>() {
@Override
public void completed(Integer bytesRead, ByteBuffer buffer) {
if (bytesRead > 0) {
buffer.flip();
result.write(buffer, buffer, new CompletionHandler<Integer, ByteBuffer>() {
@Override
public void completed(Integer result, ByteBuffer attachment) {
buffer.clear();
result.read(buffer, buffer, this);
}
@Override
public void failed(Throwable exc, ByteBuffer attachment) {
try {
result.close();
} catch (IOException e) {
e.printStackTrace();
}
}
});
}
}
@Override
public void failed(Throwable exc, ByteBuffer attachment) {
try {
result.close();
} catch (IOException e) {
e.printStackTrace();
}
}
});
}
@Override
public void failed(Throwable exc, Void attachment) {
System.err.println("Failed to accept connection: " + exc);
}
});
// Prevent the main thread from exiting
while (true) {
// The server continues to run, accepting connections
}
}
}
总结
-
BIO 适用于连接数较少且固定的情况,编程简单直观,但每个连接需要一个线程,线程资源消耗大。
-
NIO 适用于高并发的场景,通过多路复用机制(Selector)管理多个连接,提高资源利用率和性能。
-
AIO 适用于高并发、高吞吐量的场景,通过异步非阻塞 I/O 和回调机制进一步提高性能和灵活性。