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); }}
阅读全文
0 0
- Android缓存策略LruCahe源码解析,Lru到底是怎么算的?
- android缓存Lrucahe
- android开发-LRU缓存源码解析
- Lrucahe源码解析(转)
- android lru缓存 辅助类LruCache源码解析
- android开发常用的缓存策略详解(1)- LRU缓存策略
- LRU 缓存策略
- LRU 缓存策略
- LintCode-LRU缓存策略
- LRU缓存策略
- LRU缓存策略
- lintcode,LRU缓存策略
- LRU缓存策略
- LRU缓存策略设计
- LRU缓存策略设计
- LRU缓存策略-LintCode
- LRU缓存策略
- lintcode LRU缓存策略
- python下的redis连接
- Netty4.x中文教程系列(五)编解码器Codec
- 欢迎使用CSDN-markdown编辑器
- 几种使用itext生成pdf的方式
- 无法忍受sbt构建scala的龟速,用maven构建spark应用吧
- Android缓存策略LruCahe源码解析,Lru到底是怎么算的?
- 机器学习相关资料
- eclipse怎么自动生成返回对象
- ascii(hex)/aes_ecb
- Mysql使用while循环插入数据
- string,reverse,resize
- 操作系统 读者写者问题(含有swing)
- [171124][Web前端]JavaScript BOM参考
- 如何设置域名泛解析及解决恶意泛域名解析的方法