缓冲体系
体系
1 | Buffer |
Buffer
1 | public abstract class Buffer { |
Buffer是一个抽象类,类内只维护一组变量,并不维护具体的数据存储,定义了各种逻辑操作
- position:下一个操作的读写位置
- mark:标记,可以用来提示已经处理到的位置
- capacity:最大数据容量
- limit:读写的上限位置,不应操作的位置索引
可操作位置[position,limit)
0 <= mark <= position <= limit <= capacity
理解上比较直观,读写不会操作到旧数据,也不会超过上限
这一组变量的大小关系需要时刻保持
设置position
,如果设的比mark还小,说明设到了历史数据上,那么mark就失效废弃
1 | public final Buffer position(int newPosition) { |
设置limit
,如果position已经越界,那么回退position到limit,如果mark越界直接失效废弃
1 | public final Buffer limit(int newLimit) { |
标记操作
mark
只能标记下一位置,不接受参数
1 | public final Buffer mark() { |
reset
将下一操作位置设为上次标记的位置
1 | public final Buffer reset() { |
重置操作
clear
彻底恢复成初始状态,整个空间可用,limit与capacity相等
1 | public final Buffer clear() { |
flip
将缓存从输入模式转成输出模式。经过一系列输入后的position就是读出的上限
典型的使用模式:输入后输出,即先read进来再write出去
1 | buf.put(magic); |
1 | public final Buffer flip() { |
rewind
重新回到起点,可以重复读出
典型使用模式:输出后再输出一遍
1 | out.write(buf); |
1 | public final Buffer rewind() { |
clear
,flip
和rewind
都重置了当前位置和标记,不同的地方在于对上限的处理
遍历
hasRemaining
可作为标记实现类似迭代器遍历
1 | while(buf.hasRemaining()){ |
ByteBuffer
ByteBuffer是Buffer的子类,它还是抽象的,还可以进一步扩展子类
1 | public abstract class ByteBuffer extends Buffer implements Comparable<ByteBuffer> { |
字节序
- Big-Endian: 高位存低地址 0x01020304 => 01 02 03 04,01是高位存在前面,符合人类习惯
- Little-Endian: 低位存低地址 0x01020304 => 04 03 02 01
ByteBuffer默认是大端顺序,网络流中也是按照大端序,先收到的是高位
创建
ByteBuffer
创建提供了两种静态方法,建出两种不同类型的缓存
DirectBuffer
是为channel和native IO设计,可以便于让操作系统直接使用,堆外分配内存不受GC移动位置等影响,保持稳定性和连续性
如果缓存只是用于jvm内部的操作,那么HeapByteBuffer
更适用
和堆缓冲相比,直接缓冲贴近底层,读写顺序快,但是创建销毁开销很大
1 | public static ByteBuffer allocateDirect(int capacity) { |
堆Buffer还可以通过包装已有字节数组获得
1 | public static ByteBuffer wrap(byte[] array) { |
数据共享
duplicate
方法,可以共享底层数据,但是单独维护各种操作位置标记,可实现多角度灵活数据处理slice
方法,局部共享,作为原来的子数据段,从position开始一直到limit,单独维护标记asReadOnlyBuffer
方法,返回只读版本,进行数据保护
压紧
compact
操作,将没输出完的长度为n的部分(position和limit之间)复制到缓存的开端,position设为n,limit设为最大的capacity,这样接下来的写入就能直接接在后面,不会覆盖掉没读完的数据
1 | buf.clear(); // Prepare buffer for use |
版权声明
This site by Linest is licensed under a Creative Commons BY-NC-ND 4.0 International License.
由Linest创作并维护的博客采用创作共用保留署名-非商业-禁止演绎4.0国际许可证。