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

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

相关推荐
KiddoStone4 分钟前
多实例schedule job同步数据流的数据一致性设计和实现方案
java
站大爷IP18 分钟前
Python文件操作的"保险箱":with语句深度实战指南
python
运器12324 分钟前
【一起来学AI大模型】算法核心:数组/哈希表/树/排序/动态规划(LeetCode精练)
开发语言·人工智能·python·算法·ai·散列表·ai编程
岁忧25 分钟前
(LeetCode 每日一题) 1865. 找出和为指定值的下标对 (哈希表)
java·c++·算法·leetcode·go·散列表
YuTaoShao28 分钟前
【LeetCode 热题 100】240. 搜索二维矩阵 II——排除法
java·算法·leetcode
考虑考虑1 小时前
JDK9中的dropWhile
java·后端·java ee
想躺平的咸鱼干1 小时前
Volatile解决指令重排和单例模式
java·开发语言·单例模式·线程·并发编程
hqxstudying2 小时前
java依赖注入方法
java·spring·log4j·ioc·依赖
·云扬·2 小时前
【Java源码阅读系列37】深度解读Java BufferedReader 源码
java·开发语言
巴里巴气3 小时前
selenium基础知识 和 模拟登录selenium版本
爬虫·python·selenium·爬虫模拟登录