【Java基础】BIO/NIO/AIO的详细介绍与比较区分

发布时间:2024年01月18日

1 基本概念

1.1 BIO

BIO 全称 Blocking I/O,它是 JDK 1.4 之前的传统IO模型,是一种同步阻塞的IO,线程发起 IO 后,一直阻塞,直到缓冲区数据就绪后,在进入下一步操作

  • BIO存在的问题:
    • 无法应对高并发的场景
    • 连接建立后,当前线程没有数据可读就会阻塞,造成资源浪费
  • BIO适用场景:
    • 客户端连接数少
    • 并发量不高

1.2 NIO

NIO 全称 Non-Blocking I/O,也有人称之为 New /0,它是JDK 1.4 中引入的一种同步非阻塞的 I/O 模型。线程发起IO后、用户线程不需要一直等待IO缓冲区,期间可以做其他操作,只需要轮询检查IO缓冲区数据是否就绪即可。

  • NIO是基于Reactor反应堆模式实现的,分为三步:
    • 注册感兴趣的事件
    • 扫描是否有感兴趣的事情发生
    • 事件发生后做出相应的处理
  • NIO的三大核心组件
    • Channel通道:应用程序和操作系统交互事件、传递数据的通道,Channel是基于Buffer缓冲区异步的双向的数据读写通道,即可以从Buffer中读取数据,也可以向Buffer中写入数据。所有被Selector注册的通道,都只能是继承了SelectableChannel类的子类,类型有:
      • FileChannel:本地文件的读取、写入、映射和操作的通道
      • DatagramChannel:实现发送和接收UDP协议数据包的通道
      • SocketChannel:应用服务程序的监听通道,被Channel包装的ServerSocket
      • ServerSocketChannel:TCP Socket的监听通道,被Channel包装的Socket
    • Buffer缓冲区: Buffer 缓冲区,主要用于和 Channel 进行交互。以写为例,应用程序先将数据写入缓冲区,再通过通道把缓冲区的数据发送出去;读也是一样,数据先从通道读到缓冲区,应用程序再读取缓冲区的数据。Buffer 缓冲区本质上是一个字节数组,Buffer 读写数据一般遵循如下步骤:
      1. 写数据到 Buffer 缓冲;
      2. 调用 flip()方法将 Buffer 从写模式切换到读模式
      3. 从Buffer 中读取数据
      4. 调用 clear()方法或者 compact() 方法清理数据,准备下一次的写入

类型有:ByteBuffer,CharBuffer, DoubleBuffer, FloatBuffer, IntBuffer,LongBuffer,ShortBuffer; 此外还有 MappedByteBuffer,HeapByteBuffer,DirectByteBuffer 等。

  • **Selector选择器或者多路复用器:**要实现 Selector 管理 Channel,首先需要将 Channel 及其关注的事件注册在Selector 上,Selector 会不断轮询出就绪状态的 Channel 关注的事件集合,进而做相应的业务处理。通常情况下,一个线程会开启一个 Selector,而一个 Selector 可以管理多个 Channel,也就是说,一个线程就可以管理多个网络连接,即所谓的多路复用。
  • NIO适用场景:
    • 客户端连接数较多
    • 连接时间较短

1.3 AIO

AIO 全称 Asynchronous I/O,它是一种 JDK 1.7 开始支持异步非阻塞的 /0 模型。线程发起 0 请求后,不需要阻塞,立即返回异步IO操作完成后会回调通知调用方。但是,很遗憾的是,现在的IO模型使用最多的仍然是 NIO,原因很简单:Linux 系统上Java AlO 和 NIO 的底层都是基于 epoll 实现的,性能上 AIO 相比较 NIO 并没有得到很大的提升,另外,AIO 采用了异步回调、编程方式上比 NIO 要更复杂!

3 BIO/NIO/AIO的使用场景区分

使用场景如下:

  • BIO适用于连接数较少的场景
  • NIO适用于连接数目多且连接时间较短的架构,比如聊天服务器·
  • AIO适用于连接数目多且连接时间较长的架构,比如相册服务器

2 BIO和NIO的区别

BIO和NIO最大的区别并不是NIO比BIO执行速度快,而是NIO可以单个线程处理更多的连接

  • 面向流和面向缓冲区
    • Java BlO 是面向流的。每次从流中读取一个或多个字节,直至读取所有字节,它没有被缓存在任何地方,而且不能前后移动流中的数据
    • Java NIO 是面向缓冲区的。数据读取到一个它稍后处理的缓冲区,需要时可在缓冲区中前后移动,这就增加了处理过程中0的灵活性
  • 阻塞I/O和非阻塞I/O
    • Java BIO 是基于传统的I/O模型的,当一个线程调用 read()或 write()时,该线程就会被阻塞,直到有一些数据被读取,或数据完全被写入,期间不做任何事情

Java NIO 采用的是非阻塞模式,当一个线程向某通道发送请求读取数据时,它仅能读取到目前可用的数据,如果目前没有数据可读,该线程并不会保持阻塞,而是在数据变可读之前,它可以继续处理其他事情。 非阻塞写也是如此,当一个线程请求写数据到某通道时,不需要等待它完全写入,该线程可以同时去处理其他事情

  • 客户端连接盒服务端线程的对应关系
    • Java BIO:一个连接一个线程,客户端有连接请求时服务器就启动一个线程进行处理

在这里插入图片描述

  • Java NIO:一个线程可以处理多个连接请求,客户段发送的请求会注册到多路复用器上,多路复用器轮询到连接有I/O请求就会进行处理

在这里插入图片描述

文章来源:https://blog.csdn.net/weixin_45873353/article/details/135679214
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。