JAVA NIO -Buffer

JAVA NIO - Buffer

在之前提到JAVA NIO中,引入了Buffer、Channel 、Selectors.

  • Buffer:
    • 定义:
      Java NIO Buffers用于和NIO Channel交互。 我们从Channel中读取数据到buffers里,从Buffer把数据写入到Channels. Buffer本质上就是一块内存区,可以用来写入数据,并在稍后读取出来。 这块内存被NIO Buffer包裹起来,对外提供一系列的读写方便开发的接口。
    • 属性:
 // Invariants: mark <= position <= limit <= capacity
    private int mark = -1;//标志位
    private int position = 0;//当前游标(指针)位置
    private int limit;//最大容量
    private int capacity;//当前容量
  • 交互步骤:
    1.申明缓存区大小(直接缓冲区(allocateDirect)或非直接缓冲区(allocate))1
    2.把数据写入buffer;
    3.调用flip;
    4.从Buffer中读取数据;
    5.调用buffer.clear()或者buffer.compact()。

理解:

Buffer缓冲区实质上就是一块内存,用于写入数据,也供后续再次读取数据。
这块内存被NIO Buffer管理,并提供一系列的方法用于更简单的操作这块内存。
position和limit的具体含义取决于当前buffer的模式。capacity在两种模式下都表示容量。
(其实这里有点像切片的概念,指针、界限、最大容量)

  • 容量(Capacity)
    作为一块内存,buffer有一个固定的大小,叫做capacit(容量)。也就是最多只能写入容量值得字节,整形等数据。一旦buffer写满了就需要清空已读数据以便下次继续写入新的数据

  • 上限(Limit)
    在写模式,limit的含义是我们所能写入的最大数据量,它等同于buffer的容量。 一旦切换到读模式,limit则代表我们所能读取的最大数据量,他的值等同于写模式下position的位置。换句话说,您可以读取与写入数量相同的字节数(限制设置为写入的字节数,由位置标记)。(0位至 之前写模式将指针挪到的 索引位)

  • 位置(Position)
    当写入数据到Buffer的时候需要从一个确定的位置开始,默认初始化时这个位置position为0,一旦写入了数据比如一个字节,整形数据,那么position的值就会指向数据之后的一个单元,position最大可以到capacity-1. 当从Buffer读取数据时,也需要从一个确定的位置开始。buffer从写入模式变为读取模式时,position会归零,每次读取后,position向后移动。

buffer 中的绝大多数操作都是围绕以上三个属性进行操作的,

举例 :
  1. 标记当前指针位置/回退到指针位
	/**
     * Sets this buffer's mark at its position.
     *
     * @return  This buffer
     */
public final Buffer mark() {
    mark = position;
    return this;
}
/**
 回退都指针位置
 */
public final Buffer reset() {

      int m = mark;
      if (m < 0)
          throw new InvalidMarkException();
      position = m;
      return this;
}
  1. clear
public final Buffer clear() {
    position = 0;
    limit = capacity;
    mark = -1;
    return this;
}

应该明确认知clear只是改变有了游标位置等,并不会真实的清空了数据。
好比之前dubbo泛化调用中的destroy不会清除zk上的节点,而只是不watch,T_T。

  1. flip
public final Buffer flip() {
    limit = position;
    position = 0;
    mark = -1;
    return this;
}

数据存入:

当声明一组缓存区时,pos为0位。
每次读、写时,pos会+1滑动至下一个索引位;
在这里插入图片描述
在这里插入图片描述


  1. ·
    1:字节缓冲区要么是直接的,要么是非直接的。
    2:如果为直接字节缓冲区,则java虚拟机会尽最大努力直接在此缓冲区上执行本机I/O操作。再每次调用os的一个本机I/O操作时,虚拟机都会尽量避免将缓冲区的内容复制到中间的缓冲区中。
    3:直接缓冲区的内容可以驻留在常规的垃圾回收堆之外,因为对应用程序造成的内存需求影响并不明显。
    4:非直缓冲区必然存在读写时用户态与内核态的拷贝,程序无法直接通过内核态交交互OS。
    5:直接缓冲区通过形成物理内存映射文件,交互操作系统物理内存,不做拷贝。 ↩︎

发布了5 篇原创文章 · 获赞 0 · 访问量 1231

猜你喜欢

转载自blog.csdn.net/qq_39458593/article/details/105172823