LruCache和TreeMap实现 数组池 复用 android

LruCache和TreeMap实现数组池复用

  • 内存抖动--->频繁的创建对象和销毁会导致程序一直gc会导致卡顿,严重可能会导致OOM
    • LruCache
    • 通过TreeMap来记录所需数组的长度----->实现数组不同长度的复用

内存抖动—>频繁的创建对象和销毁会导致程序一直gc会导致卡顿,严重可能会导致OOM

当处理 int[] byte[] 数组时,可以创建对象数组池来进行对象的复用(减少对象的创建),降低内存抖动,提高性能。

LruCache

LruCache是一个缓存池,里面封装了LinkHashMap和一个双向链表。可以参考Glide的复用机制。
来进行数组的复用。

// An highlighted block
public class ArrayPool3 implements ArrayPool {

    private static final String TAG = "ArrayPool";

    public static final int ARRAY_POOL_SIZE_BYTES = 4 * 1024 * 1024;
    private int maxSize;

    private LruCache<Integer, byte[]> cache;
    //key 为byte数组长度,value为个数
    private final NavigableMap<Integer, Integer> sortedSizes = new TreeMap<>();

    public ArrayPool3() {
        this(ARRAY_POOL_SIZE_BYTES);
    }

    public ArrayPool3(int maxSize) {
        this.maxSize = maxSize;
        this.cache = new LruCache<Integer, byte[]>(maxSize) {
            protected int sizeOf(Integer key, byte[] value) {
                return value.length;
            }
        };
    }

    @Override
    public synchronized byte[] get(int len) {
        //获得等于或大于比len大的key
        Integer key = sortedSizes.ceilingKey(len);
        if (key != null) {
            byte[] bytes = cache.remove(key);
            //计数器 -1
            Integer current = sortedSizes.get(key);
            if (current == 1) {
                sortedSizes.remove(key);
            } else {
                sortedSizes.put(key, current - 1);
            }
            return bytes;
        }
        return new byte[len];
    }
    @Override
    public synchronized void put(byte[] data) {
        if (data == null || data.length == 0 || data.length > maxSize) return;
        int length = data.length;
        Integer current = sortedSizes.get(length);
        //计数器+1
        sortedSizes.put(length, current == null ? 1 : current + 1);
        cache.put(length, data);
    }


}

通过LruCache来进行记录 key值记录了数组的长度,value则是数组。

通过remove方法从cache中取值,通过put向cache中添加(数组使用完后调用put方法)

这样可以完成数组的复用,但是每次的length都是固定的,多大的length只能从池子中获取多大的数组(仅适用于数组大小固定)

通过TreeMap来记录所需数组的长度----->实现数组不同长度的复用

TreeMap底层的实现是红黑树,可以将key有序的排列(HashMap不可以)

		    private final NavigableMap<Integer, Integer> sortedSizes = new TreeMap<>();

把数组的长度 length 存入到TreeMap的key中,value则存放 大小为 key 的数组剩余个数。

在取值时通过 ceilingKey 可以拿到 大小 >= 所需长度length的 TreeMap的 Key

再通过拿到的 TreeMap的 key 去 cache中获取 数组,,获取到数组后将TreeMap的key对应的value减一

put时----->同样将 数组 存入 cache缓存中, 同时将 TreeMap的对应key的value值 +1

你可能感兴趣的:(android,java,开发语言,算法)