5.4.5 压缩Buffer中的数据

compact()操作将position与limit之间的元素复制到缓冲区的开始位置,从而为后续的put()/read()调用让出空间。position的值将设置为要复制的数据的长度,limit的值将设置为capacity,mark则变成未定义。考虑在下面的缓冲区调用compact()前的状态:

figure_0142_0189

下面是调用compact()后的状态:

figure_0142_0190

为什么要使用这个操作呢?假设你有一个缓冲区要写数据。回顾前面的内容我们知道,对write()方法的非阻塞调用只会写出其能够发送的数据,而不会阻塞等待所有数据发送完。因此write()方法不一定会将缓冲区中的所有元素都发送出去。又假设现在要调用read()方法,在缓冲区中没有发送的数据后面读入新数据。处理方法之一就是简单地设置position=limit和limit=capacity。当然,在读入新数据后,再次调用write()方法前,还需要将这些值还原。这样做有个问题即缓冲区的空间最终将消耗殆尽,如上图中,只剩下一个元素位置可以再存入一个字节。此外,缓冲区前面的空间又被浪费掉了。这就是compact()方法要解决的问题。在调用write()方法后和添加新数据的read()方法前调用compact()方法,则将所有“剩余”的数据移动到缓冲区的开头,从而为释放最大的空间来存放新数据。

figure_0143_0191

注意,如在本章开始已经提到的,复制数据是一个非常耗费系统资源的操作,因此要保守地使用compact()方法。