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>() {@Overridepublic void completed(AsynchronousSocketChannel result, Void attachment) {serverChannel.accept(null, this);ByteBuffer buffer = ByteBuffer.allocate(1024);result.read(buffer, buffer, new CompletionHandler<Integer, ByteBuffer>() {@Overridepublic void completed(Integer bytesRead, ByteBuffer buffer) {if (bytesRead > 0) {buffer.flip();result.write(buffer, buffer, new CompletionHandler<Integer, ByteBuffer>() {@Overridepublic void completed(Integer result, ByteBuffer attachment) {buffer.clear();result.read(buffer, buffer, this);}@Overridepublic void failed(Throwable exc, ByteBuffer attachment) {try {result.close();} catch (IOException e) {e.printStackTrace();}}});}}@Overridepublic void failed(Throwable exc, ByteBuffer attachment) {try {result.close();} catch (IOException e) {e.printStackTrace();}}});}@Overridepublic void failed(Throwable exc, Void attachment) {System.err.println("Failed to accept connection: " + exc);}});// Prevent the main thread from exitingwhile (true) {// The server continues to run, accepting connections}}
}
总结
-
BIO 适用于连接数较少且固定的情况,编程简单直观,但每个连接需要一个线程,线程资源消耗大。
-
NIO 适用于高并发的场景,通过多路复用机制(Selector)管理多个连接,提高资源利用率和性能。
-
AIO 适用于高并发、高吞吐量的场景,通过异步非阻塞 I/O 和回调机制进一步提高性能和灵活性。