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();
    }
});

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

相关推荐
ramsey171 小时前
python_excel列表单元格字符合并、填充、复制操作
python
重生之绝世牛码1 小时前
Java设计模式 —— 【行为型模式】命令模式(Command Pattern) 详解
java·大数据·开发语言·设计模式·命令模式·设计原则
Ven%2 小时前
如何让后台运行llamafactory-cli webui 即使关掉了ssh远程连接 也在运行
运维·人工智能·chrome·python·ssh·aigc
java排坑日记3 小时前
poi-tl+kkviewfile实现生成pdf业务报告
java·pdf·word
V+zmm101344 小时前
校园约拍微信小程序设计与实现ssm+论文源码调试讲解
java·微信小程序·小程序·毕业设计·ssm
猿来入此小猿4 小时前
基于SpringBoot小说平台系统功能实现四
java·spring boot·毕业设计·毕业源码·在线小说阅读·在线小说平台·免费学习:猿来入此
caron44 小时前
Python--正则表达式
python·正则表达式
是十一月末5 小时前
机器学习之过采样和下采样调整不均衡样本的逻辑回归模型
人工智能·python·算法·机器学习·逻辑回归
疯狂小料5 小时前
Python3刷算法来呀,贪心系列题单
开发语言·python·算法
Cosmoshhhyyy5 小时前
LeetCode:2274. 不含特殊楼层的最大连续楼层数(排序 Java)
java·算法·leetcode