Java的 BIO、NIO、AIO?分别的作用和用法

在Java中,BIO、NIO和AIO代表了不同的I/O操作模式。以下是每个模型的简要描述以及相应的代码示例。

BIO (Blocking I/O)

  • 作用:传统阻塞式I/O,适合低并发场景。
  • 用法 :使用java.io包中的类,如ServerSocket来监听连接请求,并为每个新连接创建一个新的线程处理读写。
java 复制代码
// 创建服务器端的ServerSocket对象,监听8080端口
ServerSocket serverSocket = new ServerSocket(8080);
while (true) {
    // 阻塞等待客户端连接
    Socket socket = serverSocket.accept();
    // 为每个客户端连接创建一个新线程
    new Thread(new ClientHandler(socket)).start();
}

class ClientHandler implements Runnable {
    private final 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 inputLine;
            while ((inputLine = in.readLine()) != null) {
                if ("bye".equals(inputLine)) break;
                out.println("Echo: " + inputLine);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try { socket.close(); } catch (IOException e) {}
        }
    }
}

NIO (Non-blocking I/O)

  • 作用:非阻塞式I/O,适合高并发场景。
  • 用法 :使用java.nio包,包括SelectorChannel接口等。
java 复制代码
// 创建Selector对象
Selector selector = Selector.open();
// 创建ServerSocketChannel并配置为非阻塞模式
ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
serverSocketChannel.configureBlocking(false);
serverSocketChannel.socket().bind(new InetSocketAddress(8080));
serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);

while (true) {
    selector.select(); // 等待就绪事件
    Set<SelectionKey> selectedKeys = selector.selectedKeys();
    Iterator<SelectionKey> iterator = selectedKeys.iterator();
    
    while (iterator.hasNext()) {
        SelectionKey key = iterator.next();
        iterator.remove();

        if (key.isAcceptable()) {
            // 处理新的客户端连接
            ServerSocketChannel ssc = (ServerSocketChannel) key.channel();
            SocketChannel clientChannel = ssc.accept();
            clientChannel.configureBlocking(false);
            clientChannel.register(selector, SelectionKey.OP_READ);
        } else if (key.isReadable()) {
            // 处理读取数据
            SocketChannel clientChannel = (SocketChannel) key.channel();
            ByteBuffer buffer = ByteBuffer.allocate(256);
            int bytesRead = clientChannel.read(buffer);
            if (bytesRead == -1) {
                clientChannel.close();
            } else {
                buffer.flip();
                byte[] data = new byte[buffer.remaining()];
                buffer.get(data);
                System.out.println("Received: " + new String(data, StandardCharsets.UTF_8));
                buffer.clear();
            }
        }
    }
}

AIO (Asynchronous I/O) 或 NIO.2

  • 作用:异步非阻塞式I/O,进一步简化并发编程。
  • 用法 :从Java 7开始提供的java.nio.channels.AsynchronousChannel及其子类,例如AsynchronousServerSocketChannelAsynchronousSocketChannel
java 复制代码
// 创建异步服务器通道
AsynchronousServerSocketChannel serverChannel = AsynchronousServerSocketChannel.open().bind(new InetSocketAddress(8080));

// 接受连接请求,设置完成处理器
serverChannel.accept(null, new CompletionHandler<AsynchronousSocketChannel, Void>() {
    @Override
    public void completed(AsynchronousSocketChannel result, Void attachment) {
        // 当接受到新的连接时,再次准备接受下一个连接
        serverChannel.accept(null, this);

        // 读取客户端发送的数据
        result.read(ByteBuffer.allocate(256), result, new CompletionHandler<Integer, AsynchronousSocketChannel>() {
            @Override
            public void completed(Integer result, AsynchronousSocketChannel channel) {
                ByteBuffer buffer = ByteBuffer.allocate(result);
                try {
                    channel.read(buffer).get();
                    buffer.flip();
                    System.out.println("Received: " + new String(buffer.array(), StandardCharsets.UTF_8));
                } catch (InterruptedException | ExecutionException e) {
                    e.printStackTrace();
                }
            }

            @Override
            public void failed(Throwable exc, AsynchronousSocketChannel channel) {
                try {
                    channel.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        });
    }

    @Override
    public void failed(Throwable exc, Void attachment) {
        exc.printStackTrace();
    }
});

请注意,这些代码片段是为了演示目的而简化了错误处理和其他细节。在实际应用中,您需要添加适当的异常处理逻辑,并根据具体需求调整资源管理和业务逻辑。

相关推荐
tb_first6 分钟前
万字超详细苍穹外卖学习笔记4
java·spring boot·笔记·学习·spring·mybatis
努力写代码的熊大22 分钟前
c++异常和智能指针
java·开发语言·c++
m0_7066532326 分钟前
用Python批量处理Excel和CSV文件
jvm·数据库·python
山岚的运维笔记27 分钟前
SQL Server笔记 -- 第15章:INSERT INTO
java·数据库·笔记·sql·microsoft·sqlserver
Yvonne爱编码27 分钟前
JAVA数据结构 DAY5-LinkedList
java·开发语言·python
witAI30 分钟前
**AI漫剧制作工具2025推荐,零成本实现专业级动画创作*
人工智能·python
小王不爱笑1321 小时前
LangChain4J 整合多 AI 模型核心实现步骤
java·人工智能·spring boot
西凉的悲伤1 小时前
spring-boot-starter-validation使用注解进行参数校验
java·spring boot·参数校验·validation·注解校验参数
LucDelton1 小时前
Java 读取无限量文件读取的思路
java·运维·网络
夹锌饼干1 小时前
mysql死锁排查流程--(处理mysql阻塞问题)
java·mysql