一、BIO(Blocking IO)—— 阻塞式 IO

概念

BIO 全称Blocking IO,即传统的阻塞式输入输出模型
在这种模式下,每个请求都由一个独立的线程来处理,线程会在 IO 操作(如 read()、accept() ) 上阻塞,直到数据准备好。

工作流程

  1. 服务端启动 ServerSocket。

  2. 调用 accept() 阻塞等待客户端连接。

  3. 为每个连接分配一个线程。

  4. 线程阻塞在 read(), 直到收到数据。

举例

ServerSocket server = new ServerSocket(8080);

while (true) {
    // 阻塞等待客户端连接
    Socket socket = server.accept();

    // 每个连接分配一个线程
    new Thread(() -> {
        try {
            InputStream in = socket.getInputStream();
            byte[] buffer = new byte[1024];
            
            // 阻塞等待客户端数据
            int len = in.read(buffer);
            
            System.out.println("收到消息:" + new String(buffer, 0, len));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }).start();
}

特点

        简单易用,编程模型直观。

        缺点是 性能差:一个连接对应一个线程,线程数多时会带来上下文切换开销,容易导致资源耗尽。

应用场景

        连接数较少、对性能要求不高的应用,例如早期的 Web 应用或小型工具型服务。


二、NIO(Non-blocking IO)—— 非阻塞 IO

概念

NIO 全称 New IO,也常被称为 Non-blocking IO,是 Java 1.4 引入的一种 基于事件驱动和多路复用 的 IO 模型。

核心组件:

Channel(通道):数据传输通道,替代传统的 Stream。

Buffer(缓冲区):数据存储容器。

Selector(选择器):单线程可管理多个通道。

工作流程

  1. 创建 ServerSocketChnnel  并设置为非阻塞模式。

  2. 注册到 Selector,监听事件(连接、读写)。

  3. 当有事件就绪时,Selector.select() 返回。

  4. 由单线程处理多个事件,而不是每个连接开线程。

举例

// 创建 Selector
Selector selector = Selector.open();

// 创建 ServerSocketChannel
ServerSocketChannel serverChannel = ServerSocketChannel.open();
serverChannel.bind(new InetSocketAddress(8080));

// 设置非阻塞
serverChannel.configureBlocking(false);

// 注册到 Selector,监听 "接收连接" 事件
serverChannel.register(selector, SelectionKey.OP_ACCEPT);

while (true) {
    // 阻塞直到有事件发生
    selector.select();

    // 获取已就绪的事件
    Set<SelectionKey> keys = selector.selectedKeys();
    for (SelectionKey key : keys) {
        if (key.isAcceptable()) {
            // 有新连接
            SocketChannel client = serverChannel.accept();
            client.configureBlocking(false);
            client.register(selector, SelectionKey.OP_READ);
        } else if (key.isReadable()) {
            // 有数据可读
            SocketChannel client = (SocketChannel) key.channel();
            ByteBuffer buffer = ByteBuffer.allocate(1024);

            int len = client.read(buffer);
            if (len > 0) {
                System.out.println("收到消息:" + new String(buffer.array(), 0, len));
            }
        }
    }
    // 清理已处理的事件
    keys.clear();
}

特点

        单线程即可处理大量连接,提升性能。

        使用 Buffer 和 Channel,比传统流(Stream)更灵活。

        编程复杂度较高,需要手动管理 Selector、Channel、Buffer。

应用场景

        高并发服务器,如聊天服务器、即时通讯系统、网关服务等。

        Netty、Tomcat、Jetty 等框架基于 NIO 封装。


三、AIO(Asynchronous IO)—— 异步 IO

概念

AIO 全称 Asynchronous IO,在 Java 7 引入。
与 NIO 的“轮询”不同,AIO 采用 事件回调机制

        发起操作后立即返回。

        当操作完成时,操作系统主动回调通知程序。

工作流程

  1. 服务端启动 AsynchronousServerSocketChnnel。

  2. 注册回调 CompletionHandler。

  3. 当有连接或数据时,系统触发回调执行。

举例

// 创建异步服务端
AsynchronousServerSocketChannel server =
        AsynchronousServerSocketChannel.open().bind(new InetSocketAddress(8080));

// 接收连接(异步回调)
server.accept(null, new CompletionHandler<AsynchronousSocketChannel, Void>() {
    @Override
    public void completed(AsynchronousSocketChannel client, Void att) {
        // 再次调用 accept 接收下一个连接
        server.accept(null, this);

        ByteBuffer buffer = ByteBuffer.allocate(1024);
        // 异步读取数据
        client.read(buffer, buffer, new CompletionHandler<Integer, ByteBuffer>() {
            @Override
            public void completed(Integer result, ByteBuffer buf) {
                buf.flip();
                System.out.println("收到消息:" + new String(buf.array(), 0, result));
            }

            @Override
            public void failed(Throwable exc, ByteBuffer buf) {
                exc.printStackTrace();
            }
        });
    }

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

特点

        完全非阻塞,线程消耗更少。

        IO 操作完成才触发回调,资源利用率高。

        Java 对不同操作系统的支持不一致,实际应用相对少。

应用场景

        超高并发、长连接场景(如消息推送、百万连接)。

        在 Linux/Unix 上结合 epoll/kqueue,性能更佳。


四、对比总结

模型BIONIOAIO
IO 特性阻塞非阻塞异步非阻塞
线程模型1 连接 1 线程1 线程多连接事件回调,无需占线程
编程难度简单中等较高
性能更高
应用场景小型应用高并发服务器超大规模并发、推送系统

理解关键点

        BIO:直来直去,容易理解,但线程开销大。

        NIO:通过 Selector 管理连接,性能好,适合大部分高并发场景。

        AIO:异步回调,理论上性能最优,但实际应用受限于底层实现。


五、总结

        Java 的 BIO、NIO 和 AIO 展示了 IO 模型的发展路径:BIO 模型简单直观,但受限于“一连接一线程”的方式,性能低;NIO 通过 Selector 实现单线程管理多连接,成为高并发场景的主流选择;AIO 则依赖异步回调机制,理论上能实现最佳性能,但受制于底层操作系统的实现差异,在实际应用中推广有限。开发者应结合业务规模与并发需求,合理选择合适的 IO 模型。

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐