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 读写数据一般遵循如下步骤:
- 写数据到 Buffer 缓冲;
- 调用 flip()方法将 Buffer 从写模式切换到读模式
- 从Buffer 中读取数据
- 调用 clear()方法或者 compact() 方法清理数据,准备下一次的写入
-
Channel通道:应用程序和操作系统交互事件、传递数据的通道,Channel是基于Buffer缓冲区的异步的双向的数据读写通道,即可以从Buffer中读取数据,也可以向Buffer中写入数据。所有被Selector注册的通道,都只能是继承了SelectableChannel类的子类,类型有:
类型有: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:一个连接一个线程,客户端有连接请求时服务器就启动一个线程进行处理
文章来源:https://www.toymoban.com/news/detail-806782.html
- Java NIO:一个线程可以处理多个连接请求,客户段发送的请求会注册到多路复用器上,多路复用器轮询到连接有I/O请求就会进行处理
文章来源地址https://www.toymoban.com/news/detail-806782.html
到了这里,关于【Java基础】BIO/NIO/AIO的详细介绍与比较区分的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!