一、Java NIO Buffer 基本介绍

缓冲区(Buffer):缓冲区本质上是一个可以读写数据的内存块,可以理解成是一个容器对象(含数组),该对象提供了一组方法,可以更轻松地使用内存块,,缓冲区对象内置了一些机制,能够跟踪和记录缓冲区的状态变化情况。Channel 提供从文件、网络读取数据的渠道,但是读取或写入的数据都必须经由 Buffer,如下图:

NIO Buffer 介绍(二) - 图1

二、Java NIO Buffer 类及其子类

在 **NIO 中,Buffer** 是一个顶层父类,它是一个抽象类,类的层级关系图
**
NIO Buffer 介绍(二) - 图2

常用Buffer子类:

  1. ByteBuffer : 存储字节数据到缓冲区
  2. ShortBuffer : 存储字符串数据到缓冲区
  3. CharBuffer : 存储字符数据到缓冲区
  4. IntBuffer : 存储整数数据到缓冲区
  5. LongBuffer : 存储长整型数据到缓冲区
  6. DoubleBuffer : 存储小数到缓冲区
  7. FloatBuffer : 存储小数到缓冲区

**Buffer 类定义了所有的缓冲区都具有的四个属性来提供关于其所包含的数据元素的信息

  • 容量(capacity):缓冲区能够容纳的数据元素的最大数量。这一容量在缓冲区创建时被设定,并且永远不能被改变
  • 上界(limit):缓冲区的第一个不能被读或写的元素。或者说,缓冲区中现存元素的计数
  • 位置(position):下一个要被读或写的元素的索引。位置会自动由相应的 get( )和 put( )函数更新
  • 标记(mark):下一个要被读或写的元素的索引。位置会自动由相应的 get( )和 put( )函数更新一个备忘位置。调用 mark( )来设定 mark = postion。调用 reset( )设定 position =mark。标记在设定前是未定义的(undefined)。这四个属性之间总是遵循以下关系:0 <= mark <= position <= limit <= capacity

    三、Java NIO Buffer 类相关方法

NIO Buffer 介绍(二) - 图3

四、Java NIO Buffer 的基本用法

使用Buffer读写数据一般遵循以下四个步骤:

  1. 写入数据到Buffer
  2. 调用flip()方法
  3. 从Buffer中读取数据
  4. 调用clear()方法或者compact()方法

当向buffer写入数据时,buffer会记录下写了多少数据。一旦要读取数据,需要通过flip()方法将Buffer从写模式切换到读模式。在读模式下,可以读取之前写入到buffer的所有数据。

一旦读完了所有的数据,就需要清空缓冲区,让它可以再次被写入。有两种方式能清空缓冲区:调用clear()或compact()方法。clear()方法会清空整个缓冲区。compact()方法只会清除已经读过的数据。任何未读的数据都被移到缓冲区的起始处,新写入的数据将放到缓冲区未读数据的后面。

举一个例子:
定义一个容量是10的buffer,填入hello:
NIO Buffer 介绍(二) - 图4

这个时候:limit代表最多写入几个,position代表即将写入的位置 ,capacity表示容器长度

当我们读取的时候,需要进行反转,也就是flip

NIO Buffer 介绍(二) - 图5

这个时候 :limit代表最多可读几个,position代表开始读的位置,capacity代表容器长度

五、代码编写Debug

经过上文对buffer类及其子类,还有相关方法、相关属性的概括,这时候编写代码进行Debug分析
案例代码如下

  1. /**
  2. * @author 王振宇
  3. * @Description <h1>举例说明buffer的使用(buffer是NIO中的三大核心之一,缓冲区,我我喜欢说成缓冲块),这里简单的说明一下</h1>
  4. * @create 2021-08-01 1:49
  5. */
  6. public class BasicBuffer {
  7. //创建一个buffer,buffer有很多类型ByteBuffer,CharBuffer,ShortBuffer,IntBuffer,LongBuffer,FloatBuffer,DoubleBuffer
  8. //这里创建建一个int类型的buffer
  9. public static void main(String[] args) {
  10. //创建了一个buffer 大小为5 存储int类型
  11. IntBuffer intBuffer = IntBuffer.allocate(5);
  12. //给buffer里面存放数据 intBuffer.capacity() buffer的容量
  13. for (int i = 0; i < intBuffer.capacity(); i++) {
  14. intBuffer.put(i*2); //buffer.put() 用于存放数据
  15. }
  16. //注意重要的操作
  17. //buffer的转换 ===读写切换
  18. intBuffer.flip();
  19. while (intBuffer.hasRemaining()){
  20. System.out.println(intBuffer.get());
  21. //注意hasRemaining()方法和get方法,他们其实维护了一个容器指针
  22. }
  23. }
  24. }
  25. 1.创建一个IntBUffer类型的长度为5buffer
  26. 2.循环存储值
  27. 3.反转(读写切换)
  28. 4.读取数据

1、在存储之前Debug代码,我们看一下IntBuffer中的属性初始化
image.png
2、当循环存储几个值后,再看一下值的变化
image.png
3、当通过filp方法反转(因为要开始读了)后,值的变化

image.png
通过Debug的形式,结合上文属性值的简单概括,深度了解一下NIO中Buffer的运行机制