Android缓存策略LruCahe源码解析,Lru到底是怎么算的?

来源:互联网 发布:知源中学复读 编辑:程序博客网 时间:2024/06/05 21:15

看前须知:

本篇文章是基于数据结构系列来写的,也是他们的后续,请至少观看过后两篇文章的读者,再来看这篇文章,推荐阅读顺序就是链接顺序,如果你不看的话,这篇文章对你毫无意义,因为只是粘贴了源码,标明了些注释,没错文章的标题就是为了无耻的导流而存在的,因为大部分人只想了解Lru算法或者LruCahe而进行搜索,而LruCache关键的核心就是使用了LinkedHashMap,你必须先知道LinkedHashMap是怎样的,而想了解LinkedHashMap你就需要了解他的父类Map和Collection接口下的LinkedList,所以请先观看相关文章。

//LinkedList源码解析,推荐阅读,因为和LinkedHashMap息息相关
http://blog.csdn.net/omyrobin/article/details/78602043

//HashMap源码解析
http://blog.csdn.net/omyrobin/article/details/78614460

//LinkedHashMap源码解析,以及怎么知道那个元素是最近最少使用的
http://blog.csdn.net/omyrobin/article/details/78624798

LruCache源码

public class LruCache<K, V> {    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;    /**     *构造函数,设置容量大小     */    public LruCache(int maxSize) {        if (maxSize <= 0) {            throw new IllegalArgumentException("maxSize <= 0");        }        this.maxSize = maxSize;        //创建了一个accessOrder为true的LinkedHashMap        this.map = new LinkedHashMap<K, V>(0, 0.75f, true);    }    /**     * Sets the size of the cache.     *     * @param maxSize The new maximum size.     */    public void resize(int maxSize) {        if (maxSize <= 0) {            throw new IllegalArgumentException("maxSize <= 0");        }        synchronized (this) {            this.maxSize = maxSize;        }        trimToSize(maxSize);    }    /**     *使用的还是map集合的get方法     */    public final V get(K key) {        if (key == null) {            throw new NullPointerException("key == null");        }        V mapValue;        synchronized (this) {            mapValue = map.get(key);            if (mapValue != null) {                hitCount++;                return mapValue;            }            missCount++;        }        /*         *         */        V createdValue = create(key);        if (createdValue == null) {            return null;        }        synchronized (this) {            createCount++;            mapValue = map.put(key, createdValue);            if (mapValue != null) {                // There was a conflict so undo that last put                map.put(key, mapValue);            } else {                size += safeSizeOf(key, createdValue);            }        }        if (mapValue != null) {            entryRemoved(false, key, createdValue, mapValue);            return mapValue;        } else {            trimToSize(maxSize);            return createdValue;        }    }    /**     *放入元素,调用的还是map的put方法     */    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;    }    /**     *容量的计算方法,通过该方法可以知道容量是否超出,如果超出需要进行删除(最近最少使用)     */    public void trimToSize(int maxSize) {        while (true) {            K key;            V value;            synchronized (this) {                if (size < 0 || (map.isEmpty() && size != 0)) {                    throw new IllegalStateException(getClass().getName()                            + ".sizeOf() is reporting inconsistent results!");                }                if (size <= maxSize) {                    break;                }                //获取最近最少使用的元素(就是header.nxt的引用)                Map.Entry<K, V> toEvict = map.eldest();                if (toEvict == null) {                    break;                }                key = toEvict.getKey();                value = toEvict.getValue();                //删除最近最少使用的元素                map.remove(key);                //重新计算size                size -= safeSizeOf(key, value);                evictionCount++;            }            entryRemoved(true, key, value, null);        }    }    /**     *     */    public final V remove(K key) {        if (key == null) {            throw new NullPointerException("key == null");        }        V previous;        synchronized (this) {            previous = map.remove(key);            if (previous != null) {                size -= safeSizeOf(key, previous);            }        }        if (previous != null) {            entryRemoved(false, key, previous, null);        }        return previous;    }    /**     *     */    protected void entryRemoved(boolean evicted, K key, V oldValue, V newValue) {}    /**     *     */    protected V create(K key) {        return null;    }    private int safeSizeOf(K key, V value) {        int result = sizeOf(key, value);        if (result < 0) {            throw new IllegalStateException("Negative size: " + key + "=" + value);        }        return result;    }    /**     *     */    protected int sizeOf(K key, V value) {        return 1;    }    /**     * Clear the cache, calling {@link #entryRemoved} on each removed entry.     */    public final void evictAll() {        trimToSize(-1); // -1 will evict 0-sized elements    }    /**     *     */    public synchronized final int size() {        return size;    }    /**     *最大size     */    public synchronized final int maxSize() {        return maxSize;    }    /**     *     */    public synchronized final int hitCount() {        return hitCount;    }    /**     *     */    public synchronized final int missCount() {        return missCount;    }    /**     * Returns the number of times {@link #create(Object)} returned a value.     */    public synchronized final int createCount() {        return createCount;    }    /**     * Returns the number of times {@link #put} was called.     */    public synchronized final int putCount() {        return putCount;    }    /**     * Returns the number of values that have been evicted.     */    public synchronized final int evictionCount() {        return evictionCount;    }    /**     * Returns a copy of the current contents of the cache, ordered from least     * recently accessed to most recently accessed.     */    public synchronized final Map<K, V> snapshot() {        return new LinkedHashMap<K, V>(map);    }    @Override public synchronized final String toString() {        int accesses = hitCount + missCount;        int hitPercent = accesses != 0 ? (100 * hitCount / accesses) : 0;        return String.format("LruCache[maxSize=%d,hits=%d,misses=%d,hitRate=%d%%]",                maxSize, hitCount, missCount, hitPercent);    }}
原创粉丝点击