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

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

相关推荐
zzzzls~25 分钟前
Python 工程化: 用 Copier 打造“自我进化“的项目脚手架
开发语言·python·copier
言慢行善33 分钟前
sqlserver模糊查询问题
java·数据库·sqlserver
韶博雅36 分钟前
emcc24ai
开发语言·数据库·python
专吃海绵宝宝菠萝屋的派大星38 分钟前
使用Dify对接自己开发的mcp
java·服务器·前端
大数据新鸟1 小时前
操作系统之虚拟内存
java·服务器·网络
Tong Z1 小时前
常见的限流算法和实现原理
java·开发语言
凭君语未可1 小时前
Java 中的实现类是什么
java·开发语言
He少年1 小时前
【基础知识、Skill、Rules和MCP案例介绍】
java·前端·python
AI_Claude_code1 小时前
ZLibrary访问困境方案四:利用Cloudflare Workers等边缘计算实现访问
javascript·人工智能·爬虫·python·网络爬虫·边缘计算·爬山算法
克里斯蒂亚诺更新1 小时前
myeclipse的pojie
java·ide·myeclipse