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 中的绝大多数操作都是围绕以上三个属性进行操作的,
举例 :
- 标记当前指针位置/回退到指针位
/**
* 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;
}
- clear
public final Buffer clear() {
position = 0;
limit = capacity;
mark = -1;
return this;
}
应该明确认知clear只是改变有了游标位置等,并不会真实的清空了数据。
好比之前dubbo泛化调用中的destroy不会清除zk上的节点,而只是不watch,T_T。
- flip
public final Buffer flip() {
limit = position;
position = 0;
mark = -1;
return this;
}
数据存入:
当声明一组缓存区时,pos为0位。
每次读、写时,pos会+1滑动至下一个索引位;
·
1:字节缓冲区要么是直接的,要么是非直接的。
2:如果为直接字节缓冲区,则java虚拟机会尽最大努力直接在此缓冲区上执行本机I/O操作。再每次调用os的一个本机I/O操作时,虚拟机都会尽量避免将缓冲区的内容复制到中间的缓冲区中。
3:直接缓冲区的内容可以驻留在常规的垃圾回收堆之外,因为对应用程序造成的内存需求影响并不明显。
4:非直缓冲区必然存在读写时用户态与内核态的拷贝,程序无法直接通过内核态交交互OS。
5:直接缓冲区通过形成物理内存映射文件,交互操作系统物理内存,不做拷贝。 ↩︎