Lru源码分析

首先 我们从他的构造方法及属性看起

 private final LinkedHashMap<K, V> map;
/** Size of this cache in units. Not necessarily the number of elements. */
private int size;
private int maxSize;

private int putCount;
private int createCount;
private int evictionCount;
private int hitCount;
private int missCount;

/**
 * @param maxSize for caches that do not override {@link #sizeOf}, this is
 *     the maximum number of entries in the cache. For all other caches,
 *     this is the maximum sum of the sizes of the entries in this cache.
 */
public LruCache(int maxSize) {
    if (maxSize <= 0) {
        throw new IllegalArgumentException("maxSize <= 0");
    }
    this.maxSize = maxSize;
    this.map = new LinkedHashMap<K, V>(0, 0.75f, true);
}

从构造方法可以看出 需要传入一个Int值 和new了一个LinkedHashMap对象 然后我们接着往后面的方法看

/**
 * Sets the size of the cache.
 * @param maxSize The new maximum size.
 *
 * @hide
 */
public void resize(int maxSize) {
    if (maxSize <= 0) {
        throw new IllegalArgumentException("maxSize <= 0");
    }

    synchronized (this) {
        this.maxSize = maxSize;
    }
    trimToSize(maxSize);
}

首先我们从上面的注解可以知道这个是设置缓存大小的方法 我们可以看出 它吧从构造函数传过来的 maxsize这个值放入了 trimToSize(maxSize); 这个方法中 接着我们进入这个方法里面去看看

/**maxSize 表示在返回内存大小之前的最大数值
 * @param maxSize the maximum size of the cache before returning. May be -1
 *     to evict even 0-sized elements.
 */
private void trimToSize(int maxSize) {
    while (true) {
        K key;
        V value;
        synchronized (this) {
               //判断集合是否为空 size是否小于0
            if (size < 0 || (map.isEmpty() && size != 0)) {
                throw new IllegalStateException(getClass().getName()
                        + ".sizeOf() is reporting inconsistent results!");
            }
              如果小于设定的最大值 则跳出循环
            if (size <= maxSize) {
                break;
            }

            // BEGIN LAYOUTLIB CHANGE
            // get the last item in the linked list.
            // This is not efficient, the goal here is to minimize the changes
            // compared to the platform version.
             //遍历 LinkedHashMap 双向链表的元素,取得队列尾部的元素(就是我们所说的过期元素),如果它不为空,就将它移除。
            Map.Entry<K, V> toEvict = null;
            for (Map.Entry<K, V> entry : map.entrySet()) {
             //不断的把entry 的值赋给toEvict 直到最后一个
                toEvict = entry;
            }
            // END LAYOUTLIB CHANGE

            if (toEvict == null) {
                break;
            }

            key = toEvict.getKey();
            value = toEvict.getValue();
          //移除最后一个元素
            map.remove(key);
                      /*
    private int safeSizeOf(K key, V value) {
    int result = sizeOf(key, value);
    if (result < 0) {
        throw new IllegalStateException("Negative size: " + key + "=" + value);
    }
    return result;
 }
*/              
     //判断移除后的缓存大小
    size -= safeSizeOf(key, value);
            evictionCount++;
        }
        entryRemoved(true, key, value, null);
    }
}

最主要的方法分析完了 再看看其他的

 public final V put(K key, V value) {
    if (key == null || value == null) {
        throw new NullPointerException("key == null || value == null");
    }

    V previous;
    synchronized (this) {
        putCount++;
       //计算缓存大小
        size += safeSizeOf(key, value);
        previous = map.put(key, value);
        if (previous != null) {
            size -= safeSizeOf(key, previous);
        }
    }

    if (previous != null) {
        entryRemoved(false, key, previous, value);
    }
  //调用方法 淘汰不用的缓存
    trimToSize(maxSize);
    return previous;
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。