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包,包括Selector、Channel接口等。
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及其子类,例如AsynchronousServerSocketChannel和AsynchronousSocketChannel。
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();
    }
});

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

相关推荐
天天被压力9 分钟前
【A股分钟级高频数据完全手册 #07】北交所历史分钟K线接口:京市Pro版分时批量
java·人工智能·python
天天被压力15 分钟前
【A股分钟级高频数据完全手册 #08】股票日、分时数据接口对比:普通分时与Pro版差异实测
java·人工智能·python
特立独行的猫A29 分钟前
AI 时代,我为什么推荐用 cj-tauri 开发桌面应用
java·后端·python
金銀銅鐵32 分钟前
从一个类名到一张类图:用反射自动生成 PlantUML
java·后端·uml
小lo想吃棒棒糖1 小时前
把机器人训练从 GPU 搬到昇腾 NPU:启元 Q1 起身动作 PPO 训练全记录
python·机器人·昇腾·启元机器人
Thanks_ks1 小时前
【第 006 讲】搭建 PyCharm 开发环境:PyCharm 的下载与安装 | 初始设置与常用配置
ide·python·pycharm·开发工具·jetbrains·开发环境·集成开发环境
nice_lcj5201 小时前
Java 并发容器入门:ConcurrentHashMap、CopyOnWriteArrayList、阻塞队列
java·面试·并发编程·阻塞队列·concurrenthashmap·copyonwritearraylist
微小的鱼1 小时前
Linux的渲染与显示系统链路
android·java·linux
青少儿编程课堂2 小时前
蓝桥杯青少组图形化省考报名倒计时·全国青少年信息素养大赛·电子学会图形化考级:校园黑白棋人机对战解析
c++·python·算法·bfs·信息学竞赛
若亦_2 小时前
Java中关于this的三种用法
java·开发语言·intellij-idea