属性名 | 作用 | 类型 |
---|---|---|
mBuffersByLastUse | 按照最近使用对byte[]排序 | LinkedList |
mBuffersBySize | 按照byte[]大小对byte[]排序 | ArrayList |
[code] public synchronized byte[] getBuf(int len) { for (int i = 0; i < mBuffersBySize.size(); i++) { byte[] buf = mBuffersBySize.get(i); if (buf.length >= len) { mCurrentSize -= buf.length; mBuffersBySize.remove(i); mBuffersByLastUse.remove(buf); return buf; } } return new byte[len]; }方法的第2行代码,遍历mBuffersBySize,找到最适合len大小的byte[]。第6 ~8行更新缓存池中数据的大小,并从两个数组中去除分配出去的byte[]。如果在缓存池中没有要求的byte[],此时会从内存分配一跨区域返回。
此方法主要的功能: 不必每次存数据都要进行内存分配,而是先查找缓冲池中有无适合的内存区域,如果有,直接拿来用,从而减少内存分配的次数。 其实这个方法有改进空间:由于在类中有一个mSizeLimit属性,表示此缓冲区的最大值。我们可以在方法体的第一行判断 len与mSizeLimit的大小,如否 len>mSizeLimit,直接进入到最后一句运行,否则,循环。修改后的方法如下:
= len) { mCurrentSize -= buf.length; mBuffersBySize.remove(i); mBuffersByLastUse.remove(buf); return buf; } } } return new byte[len]; }" data-snippet-id="ext.3a74a1521d5a658f08c49df9e1de15fb" data-snippet-saved="false" data-csrftoken="mVnBxipq-LBho6kln963iLFcIOaE1zURmRSI" data-codota-status="done">[code]public synchronized byte[] getBuf(int len) { //有的条件不需循环 if(len<=mSizeLimit) { for (int i = 0; i < mBuffersBySize.size(); i++) { byte[] buf = mBuffersBySize.get(i); if (buf.length >= len) { mCurrentSize -= buf.length; mBuffersBySize.remove(i); mBuffersByLastUse.remove(buf); return buf; } } } return new byte[len]; }将空间返回给缓存池
如果只是拿数据,缓存区的只会越来越小,我们还需要向缓冲区中加入存储空间。这个时候涉及到一个方法:returnBuf(byte[])。[code] public synchronized void returnBuf(byte[] buf) { if (buf == null || buf.length > mSizeLimit) { return; } mBuffersByLastUse.add(buf); int pos = Collections.binarySearch(mBuffersBySize, buf, BUF_COMPARATOR); if (pos < 0) { pos = -pos - 1; } mBuffersBySize.add(pos, buf); mCurrentSize += buf.length; trim(); }方法首先检查 要插入的数据大小有没有超出边界,如果没有,利用二分法找到插入位置,将数据插入到上述的两个集合,完成排序。然后更新缓冲池的大小,以方便从缓冲区中取存储空间。结语
ByteArrayPool利用getBuf和returnBuf以及mBuffersByLastUse和mBuffersBySize完成字节数组的缓存。当需要使内存区域的时候,先从已经分配的区域中获得以减少内存分配次数。当空间用完以后,在将数据返回给此缓冲区。这样,就会减少内存区域堆内存的波动和减少GC的回收,让CPU把更多的性能留给页面的渲染,提高性能。通过这个类发现,谷歌对技术的细节十分考究。
新闻热点
疑难解答