LRUCache的实现原理
来源:互联网 发布:淘宝内部优惠券怎么弄 编辑:程序博客网 时间:2024/05/29 09:42
简介
LRU(Least Recently Used)最近最少使用,最近有时间和空间最近的歧义,所以我更喜欢叫它近期最少使用算法。它的核心思想是,如果一个数据被访问过,我们有理由相信它在将来被访问的概率就越高。于是当LRU缓存达到设定的最大值时将缓存中近期最少使用的对象移除。LRUCache内部使用LinkedHashMap来存储key-value键值对,并将LinkedHashMap设置为访问顺序来体现LRU算法。
简单使用
// 拿到当前的最大内存long maxMemory = Runtime.getRuntime().maxMemory();int cacheSize = (int) (maxMemory / 8);// 将LruCache的缓存容量设置为cacheSize,并重写sizeOf方法。lruCache = new LruCache<String, Bitmap>(cacheSize) { @Override protected int sizeOf(String key, Bitmap value) { return value.getByteCount(); }};// put一条数据lruCache.put(key, bitmap);// get一条数据lruCache.get(key);// remove一条数据lruCache.remove(key);
数据结构
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); }
可以看到,除了初始化maxSize,还初始化了一个全局的LinkedHashMap,当第三个参数设为true时,map被设置为
访问顺序,也就是每操作一次map的某个Entry,它就会被放到双向链表的队尾。也就是说LRU算法的任务,完全交给了LinkedHashMap。
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); // 如果key不冲突就返回null // 如果key冲突就用value替换odlValue,并返回oldValue previous = map.put(key, value); if (previous != null) { size -= safeSizeOf(key, previous); } } if (previous != null) { entryRemoved(false, key, previous, value); } trimToSize(maxSize); return previous; }
数据通过key-value的形式被put到了map里,在put之前通过sizeOf方法计算value的size,并累加到全局变量size里,它用来记录当前缓存的数据大小。sizeOf原则上必须重写,用来定义自己的计算规则。然后调用了trimToSize方法,这个方法用以保证缓存大小不会超过maxSize。
trimToSize方法
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 || map.isEmpty()) { break; } Map.Entry<K, V> toEvict = map.entrySet().iterator().next(); key = toEvict.getKey(); value = toEvict.getValue(); map.remove(key); size -= safeSizeOf(key, value); evictionCount++; } entryRemoved(true, key, value, null); } }
一进来就是一个死循环,然后就迭代删除位于队首的数据。只有当前缓存容量小于maxSize的时候才break。
综上
LruCache自己主要是实现maxSize的判断,以及通过trimToSize对缓存的裁剪。其他存储、提取数据的方法以及LRU的算法都是借助LinkedHashMap来实现的。
0 0
- LRUCache的实现原理
- LruCache的实现原理(图片三级缓存)
- LruCache实现原理
- LruCache 实现原理分析
- LruCache 实现原理分析
- 内存缓存LruCache实现原理
- 内存缓存LruCache实现原理
- Android LruCache 实现原理解析
- 内存缓存LruCache实现原理
- 内存缓存LruCache实现原理
- 内存缓存LruCache实现原理
- LruCache(内存缓存)的原理
- LruCache原理
- LruCache原理
- mybatis-3的LruCache实现
- LRUCache算法的简单实现
- Lrucache算法的原理简要分析
- LRUCache原理及HashMap LinkedHashMap内部实现原理
- Kurento应用开发指南(以Kurento 5.0为模板) 之二:示例教程helloworld
- 基础-6 fragment
- 常见内存泄漏分析
- canvas-矩形
- eclipse Project Explorer 小窗口工具栏介绍
- LRUCache的实现原理
- oracle 按日期条件查询 to_date
- Android SeekBar拖动条
- 类型参数的约束(C# 编程指南)
- 代码初始化提交到svn, AndroidStudio关联SVN
- HDU 2586 How far away ?(map+lca【暴力水】)
- bzoj 2406: 矩阵 (有上下界的网络流)
- Linux下压缩、解压缩
- request.getInputStream()只能获取一次的问题