BIO,NIO,AIO的区别

1.概览

  1. BIO(Blocking I/O)就像你亲自去咖啡店点一杯咖啡,然后等待咖啡师傅为你泡制咖啡。在这个过程中,你需要一直等待,不能做其他事情,知道咖啡师傅完成工作并将咖啡交给你。这中方式非常耗时,而且你需要专门的人员为每个人制证咖啡。
  2. NIO(Non-Blocking I/O)就像在咖啡店里使用自助咖啡机。你可以插入咖啡杯,按下按钮开始制作咖啡,然后继续等待。当咖啡准备好时,机器会通知你,你可以拿起咖啡杯,在这个过程中,你可以做其他事情,只要不断关注咖啡机是否完成。
  3. AIO(Asynchronous I/O)就像你再咖啡订购应用中预想下单并设置好提醒。

2.区别

它们有以下区别:

2.1.阻塞/非阻塞

        BIO是阻塞式的I/O模型,即在进行I/O操作时,线程会一直阻塞等待数据的读取或者写入。        

        NIO是非阻塞式的I/O模型,它通过使用选择器(Selector)和通道(Channel)的概念,使得线程在进行I/O操作时可以立即返回,而不需要一直等待数据就绪。

        AIO也是非阻塞的,但相较于NIO,它更加高级和异步,可以通过回调机制在操作完成时通知应用程序。

2.2.同步/异步

        BIO是同步的,意味着线程会等待I/O操作的完成。

        NIO是同步或者异步的,可以同步选择气的不同模式来实现。

        AIO是异步的,即在进行I/O操作时,线程可以继续处理其他任务,而无需等待I/O操作的完成。        

2.3.线程模型

        BIO采用传统的一对一线程模型,即每个连接都需要一个独立的线程来处理。这回导致线程数量随着连接数增加而增加,容易造成资源的浪费。

        NIO采用较为高效的多路复用器(Selector)机制,使用少量的线程来处理多个连接。

        AIO采用基于事件驱动的线程模型,通过回调机制实现异步处理。

2.4.编程复杂度

        BIO编程较为简单,但由于是阻塞式的,可能会导致性能瓶颈。

        NIO编程较为复杂,需要了解选择器、通道和缓冲区等概念,但可以提供更好的性能和扩展性。

        AIO编程相对更复杂,需要处理回调函数和处理器,但能够提供更高并发性和可伸缩性。

2.5.小结

        选择何种I/O模型取决于具体应用程序的需求。如果应用程序的连接数较少且并发性要求不高,可以选择BIO。如果要求高并发性、较低的线程开销和更好的可扩展行,可以选择NIO。如果需要处理大量的并发连接,并希望通过异步操作来提高性能,可以选择AIO。

3.在java中的应用

        当涉及到Java中的BIO、NIO和AIO时,我们可以使用Socket编程作为例子来解释它们的区别。

3.1.BIO

try (ServerSocket serverSocket = new ServerSocket(8080)) {
    while (true) {
        Socket socket = serverSocket.accept();  // 阻塞等待客户端连接
        // 处理客户端请求,创建线程或线程池来处理每个连接
    }
} catch (IOException e) {
    e.printStackTrace();
}

        在这个例子中,使用了阻塞式的'ServerSocket'和'Socket'。'accept()'方法会阻塞等待客户端的连接,直到客户端连接进来。在这期间,主线程会一直等待,直到有新的连接进来才会继续执行。

3.2.NIO

try (ServerSocketChannel serverSocketChannel = ServerSocketChannel.open()) {
    serverSocketChannel.bind(new InetSocketAddress(8080));
    serverSocketChannel.configureBlocking(false);  // 设置为非阻塞模式

    Selector selector = Selector.open();
    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();
            if (key.isAcceptable()) {
                ServerSocketChannel serverChannel = (ServerSocketChannel) key.channel();
                SocketChannel socketChannel = serverChannel.accept();  // 非阻塞获取客户端连接
                // 处理客户端请求,创建线程或线程池来处理每个连接
            }
            iterator.remove();
        }
    }
} catch (IOException e) {
    e.printStackTrace();
}

        在这个例子中,使用了NIO的'ServerSocketChannel'和'SocketChannel'。首先,将'ServerSocketChannel'设置为非阻塞模式。然后,通过选择器('Selector')监听连接事件,当有连接到达时,通过非阻塞方式获取客户端连接。这样可以避免主线程一直等待,可以同时处理多个连接。

3.3.AIO 

AsynchronousServerSocketChannel serverSocketChannel = AsynchronousServerSocketChannel.open();
serverSocketChannel.bind(new InetSocketAddress(8080));

serverSocketChannel.accept(null, new CompletionHandler<AsynchronousSocketChannel, Void>() {
    @Override
    public void completed(AsynchronousSocketChannel result, Void attachment) {
        // 处理客户端请求,不需要阻塞等待连接
        serverSocketChannel.accept(null, this);
    }

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

Thread.sleep(Long.MAX_VALUE);

        在这例子中,使用了AIO的'AsynchronousServerSocketChannel'和'AsynchronousSocketChannel'。通过异步方式监听连接事件,并在连接到达时调用回调方法'completed()'来处理客户端请求。这样,不需要阻塞等待连接,而是通过回调方式处理连接事件。

3.4.小结

        这些例子展示了在Java中使用不同I/O模型的代码示例。BIO是阻塞的,需要一直等待连接;NIO是非阻塞式的,可以同时处理多个连接;AIO是异步的,通过回调方式处理连接事件,无需等待。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值