缓冲区(Buffer)

在Java NIO 中负责数据的存取,缓冲区就是数组,用于存储不同类型的数据,为所有的原始类型(boolean类型除外)提供缓存支持的数据容器,使用它可以提供非阻塞式的高伸缩性网络。

缓冲区类型

缓冲区类型 描述 备注
ByteBuffer 字节类型缓冲区
CharBuffer 字符类型缓冲区
DoubleBuffer 双精度浮点型缓冲区
FloatBuffer 单精度浮点型缓冲区
IntBuffer 整型缓冲区
LongBuffer 长整型缓冲区
ShortBuffer 短整型缓冲区

上述缓冲区的管理方式几乎一致,通过 allocate() 获取缓冲区

缓冲区的两个核心方法

存入数据到缓冲区中put():

  • put(byte b):将给定单个字节写入缓冲区的当前位置
  • put(byte[] src):将 src 中的字节写入缓冲区的当前位置
  • put(int index, byte b):将指定字节写入缓冲区的索引位置(不会移动 position)

获取缓冲区中的数据get():

  • get() :读取单个字节
  • get(byte[] dst):批量读取多个字节到 dst 中
  • get(int index):读取指定索引位置的字节(不会移动 position)

    缓冲区的四个核心属性

  • mark :标记

  • position:位置,表示缓冲区中正在操作数据的位置
  • limit:界限,表示缓冲区中可以操作数据的大小。(limit后面的数据不能进行读写操作)
  • capacity:容量 表示缓冲区中最大存储数据的容量,一单声明不能改变

    0 <= mark <= position <= limit <= capacity

直接缓冲区与非直接缓冲区

Java8操作手册:

  • 字节缓冲区是直接 或非直接的 。 给定一个直接字节缓冲区,Java虚拟机将尽力在其上直接执行本地I / O操作。 也就是说,它将尝试避免在每次调用其中一个底层操作系统的本机I / O操作之前(或之后)将缓冲区的内容复制到(或从)中间缓冲区。
  • 可以通过调用此类的allocateDirect工厂方法来创建直接字节缓冲区。 此方法返回的缓冲区通常比非直接缓冲区具有更高的分配和释放成本。 直接缓冲区的内容可能驻留在正常的垃圾回收堆之外,因此它们对应用程序的内存占用的影响可能不明显。 因此,建议直接缓冲区主要用于受基础系统本机I / O操作影响的大型长寿命缓冲区。 一般来说,最好只在产生程序性能可测量的增益时才分配直接缓冲区。
  • 直接字节缓冲区也可以由文件的mapping直接创建到内存区域。 Java平台的实现可以可选地支持通过JNI从本地代码创建直接字节缓冲器。 如果这些缓冲区之一的实例指的是存储器的不可访问的区域,则访问该区域的尝试将不会改变缓冲区的内容,并且将导致在访问时或之后的某个未指定的异常时间。
    字节缓冲区是直接还是非直接可以通过调用其isDirect方法来确定 。 提供了这种方法,使得可以在性能关键代码中进行显式缓冲区管理。

image.pngimage.png

字节缓冲区分为两种情况:

  • 非直接缓冲区:通过 allocate() 方法分配缓冲区,将缓冲区建立在JVM的内存中
  • 直接缓冲区:通过 allocateDirect() 方法分配直接缓冲区,将缓冲区建立在物理内存中(效率高,不安全,不受控制、GC才可以销毁)