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 模型取决于具体的应用场景及性能要求。

点赞(0) 打赏

微信小程序

微信扫一扫体验

微信公众账号

微信扫一扫加关注

发表
评论
返回
顶部