Java I/O(输入/输出)系统包含多种处理方式,主要包括 BIO(Blocking I/O)、NIO(Non-blocking I/O)和 AIO(Asynchronous I/O)。这三种模型各有其特点和适用场景,本文将对它们进行详细的讲解并提供相应的代码示例。
一、BIO(Blocking I/O)
BIO 是最基础的 I/O 模型。在这种模型中,线程在进行 I/O 操作时会被阻塞,直到操作完成。这意味着如果有多个客户端同时连接到服务器,每个连接都会占用一个线程,如果线程数过多,会导致系统资源耗尽,性能下降。
特点:
- 简单易用,编程模型直观。
- 存在阻塞现象,不适合高并发场景。
示例代码:
import java.io.*;
import java.net.*;
public class BioServer {
public static void main(String[] args) throws IOException {
ServerSocket serverSocket = new ServerSocket(8080);
System.out.println("服务端已启动,等待连接...");
while (true) {
Socket socket = serverSocket.accept();
new Thread(new ClientHandler(socket)).start();
}
}
}
class ClientHandler implements Runnable {
private Socket socket;
public ClientHandler(Socket socket) {
this.socket = socket;
}
@Override
public void run() {
try (BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
PrintWriter out = new PrintWriter(socket.getOutputStream(), true)) {
String line;
while ((line = in.readLine()) != null) {
System.out.println("收到信息: " + line);
out.println("消息已接收: " + line);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
二、NIO(Non-blocking I/O)
NIO 在 Java 1.4 中引入,提供了非阻塞的 I/O 操作。在 NIO 模型下,可以使用 Selector 来管理多个通道(Channel),允许单个线程处理多个连接。这大大提高了资源的利用率和性能。
特点:
- 支持非阻塞操作,适合高并发应用。
- 使用 Selector 可以处理多个连接,降低线程开销。
示例代码:
import java.io.*;
import java.net.*;
import java.nio.*;
import java.nio.channels.*;
import java.util.*;
public class NioServer {
public static void main(String[] args) throws IOException {
Selector selector = Selector.open();
ServerSocketChannel serverChannel = ServerSocketChannel.open();
serverChannel.bind(new InetSocketAddress(8080));
serverChannel.configureBlocking(false);
serverChannel.register(selector, SelectionKey.OP_ACCEPT);
System.out.println("NIO 服务端已启动...");
while (true) {
selector.select();
Set<SelectionKey> selectedKeys = selector.selectedKeys();
Iterator<SelectionKey> iterator = selectedKeys.iterator();
while (iterator.hasNext()) {
SelectionKey key = iterator.next();
if (key.isAcceptable()) {
SocketChannel clientChannel = serverChannel.accept();
clientChannel.configureBlocking(false);
clientChannel.register(selector, SelectionKey.OP_READ);
System.out.println("客户端已连接: " + clientChannel.getRemoteAddress());
} else if (key.isReadable()) {
SocketChannel clientChannel = (SocketChannel) key.channel();
ByteBuffer buffer = ByteBuffer.allocate(256);
int bytesRead = clientChannel.read(buffer);
if (bytesRead > 0) {
String message = new String(buffer.array()).trim();
System.out.println("收到信息: " + message);
clientChannel.write(ByteBuffer.wrap(("消息已接收: " + message).getBytes()));
} else {
clientChannel.close();
}
}
iterator.remove();
}
}
}
}
三、AIO(Asynchronous I/O)
AIO 是在 Java 7 引入的异步 I/O 模型,允许在 I/O 操作时注册一个回调。当 I/O 操作完成时,回调方法会被触发,可更高效地利用系统资源。
特点:
- 完全非阻塞的 I/O,可以实现高性能和高并发。
- 编程模型相对复杂,适合处理 I/O 密集型任务。
示例代码:
import java.nio.channels.*;
import java.nio.file.*;
import java.util.concurrent.*;
public class AioExample {
public static void main(String[] args) {
AsynchronousFileChannel channel;
try {
channel = AsynchronousFileChannel.open(Paths.get("test.txt"), StandardOpenOption.READ);
ByteBuffer buffer = ByteBuffer.allocate(1024);
Future<Integer> result = channel.read(buffer, 0);
System.out.println("I/O 操作正在进行...");
// 可以做其他事情
while (!result.isDone()) {
// 其他逻辑
}
System.out.println("I/O 操作完成,读取字节数: " + result.get());
buffer.flip();
System.out.println(new String(buffer.array(), 0, result.get()));
} catch (Exception e) {
e.printStackTrace();
}
}
}
总结
BIO、NIO 和 AIO 各具优缺点。对于需求简单、并发量不高的场景,BIO 就足够了。而在高并发的情况下,NIO 由于其非阻塞特性能够显著提高性能。而 AIO 则更适合需要处理大量异步 I/O 任务的应用,比如文件服务器或高性能网络应用。选择合适的 I/O 模型取决于具体的应用场景及性能要求。