缓冲区由当前的多个线程使用是不安全的。如果一个缓冲区由不止一个线程使用,则应该通过适当的同步来控制对该缓冲区的访问。
缓冲区有以下四个属性:
- capacity (容量):缓冲区的容量是它所包含的元素的数量。缓冲区的容量永远不会为负并且从不会更改。
- limit (限制):缓冲区的限制是不应读取或写入的第一个元素的索引。缓冲区的限制永远不会为负,并且永远不会大于其容量。
- position (位置):缓冲区的位置是下一个要读取或写入的元素的索引。缓冲区的位置永远不会为负,并且永远不会大于其限制。
- mark (标记):缓冲区的标记是在调用reset 方法时其位置将被重置到该mark位置。如果定义的标记后,位置(position)或限制(limit)调整为小于标记的值时,该标记将被丢弃。如果未定义标记,则调用 reset 方法将导致抛出InvalidMarkException。
传输数据定义了两种get和put操作:
相对操作 :操作读取或写入从当前位置开始的一个或多个元素,然后将该位置增加传输的元素的数量。
绝对操作 :操作采用显式元素索引,不会影响位置。
四属性之间的关系
0 <= 标记(mark) <= 位置(position) <= 限制(limit) <= 容量(capacity)
新创建的缓冲区位置为零(position = 0)和标记未定义(mark = -1)。初始限制可以为零,也可以是其他某个值,这取决于缓冲区类型及其构建方式。一般情况下,缓冲区的初始内容未定义。
clear() 清除此缓冲区。将位置设置为零,限制设置为该容量,并且丢弃标记。 源码:
position = 0;
limit = capacity;
mark = -1;
在get或put操作填充此缓冲区之前调用此方法。例如:
buf.clear(); // 准备写
in.read(buf); // 读取
注:此方法并没有实际擦除缓冲区中的数据。
flip() 反转此缓冲区。首先将当前位置设置为限制,然后将该位置设置为零。如果已定义了标记,则丢弃该标记。源码如下:
limit = position;
position = 0;
mark = -1;
在缓冲读取或put操作之后,调用此方法以做好缓冲写入或相对get操作。例如:
buf.put(magic); // 预置报头
in.read(buf); // 从输入通道中读取数据并紧跟在报送后存放
buf.flip(); // 准备读
out.write(buf); // 把头与体写到输出通道
当将数据从一个地方传输到另一个地方时,经常将此方法与compact方法一起使用。
rewind() 重置此缓冲区。将位置设置为零并丢弃标记。 源码如下:
position = 0;
mark = -1;
在缓冲重新写入或get操作之前调用此方法(假定已经适当设置了限制)。例如:
out.write(buf); // 剩余数据写入输出通道
buf.rewind(); // 重绕
buf.get(array); // 复制数据到array
mark() 在此缓冲区的位置设置其标记, 把mark设为position 。源码如下:
mark = position;
reset() 将此缓冲区的位置重新设置成以前标记的位置。 调用此方法既不会更改也不会丢弃标记的值。 源码如下:
position = mark;
其他方法:
capacity() : 返回buffer的capacity(容量)
limit() :返回此缓冲区的限制 limit的值 。
limit(int lim) :设置limit的值。
position() :返回此缓冲区的位置 position 。
position(int pos) :设置position的值。
remaining() :返回当前位置与限制之间的元素数量 (limit - position) 。
hasRemaining() :如果position和limit之间还有数据,就返回true。