Buffer本质上就是一块可以重复进行读写的内存空间,为了理解它是如何使用内存来进行读写,需要理解如下的三个概念:
- capacity:容量,缓冲区的总长度,如果缓冲区已满还需要写入数据,就需要先清空再写入
- position:位置,下一个要操作的数据元素的位置。起始位置为0,随着数据的写入不断的后移,最大为capacity - 1。当从buffer中读取数据时,position重置回0,记录下一个要读取数据的位置
- limit:缓冲区中不可操作的下一个元素的位置,用于限制程序可以写入或者读取的数据量,通常为limit <=capacity
读取的数据量不能超过写入的数据量。
Buffer有两种模式,写模式和读模式。在写模式下调用flip()之后,Buffer从写模式变成读模式。如果想要从写模式转换到读模式,则可以调用clear方法或是compact方法。
flip方法的源码如下:
public final Buffer flip() {
limit = position;
position = 0;
mark = -1;
return this;
}
flip方法主要做了如下三步:
- 设置limit值为最后的position值
- 将position值置为0
- 清除mark标记
假设Buffer的容量大小为8,初始时Buffer示意图如下所示:
然后往Buffer中写入5个数据,变成如下的情况:
调用flip方法后,position、limit和capacity的变化如下所示:
此时position指到Buffer头部,并且limit移动到之前position的位置,表示最多只能读出之前写入的数据长度(而不是整个缓存的容量大小)。这样在执行读操作时,从头读取,并且最多只能读取之前写入的数据量。
最后,通过程序验证下上述的流程,如下所示:
/**
* @Author dyliang
* @Date 2020/10/25 9:17
* @Version 1.0
*/
public class BufferTest {
private static final int BUFFER = 8;
public static void main(String[] args){
IntBuffer buffer = IntBuffer.allocate(BUFFER);
System.out.println("-------------before--------------");
System.out.println("position is: " + buffer.position());
System.out.println("limit is: " + buffer.limit());
System.out.println("capacity is: " + buffer.capacity());
for (int i = 0; i < 5; i++) {
buffer.put(i);
}
buffer.flip();
System.out.println("-------------after--------------");
System.out.println("position is: " + buffer.position());
System.out.println("limit is: " + buffer.limit());
System.out.println("capacity is: " + buffer.capacity());
System.out.println("--------------------------------");
while(buffer.hasRemaining()){
System.out.println(buffer.get());
}
}
}
程序输出:
-------------before--------------
position is: 0
limit is: 8
capacity is: 8
-------------after--------------
position is: 0
limit is: 5
capacity is: 8
--------------------------------
0
1
2
3
4