目录

0、相关文章:

1、源码分析:

2、为什么用LinkedHashMap


0、相关文章:

LRUCache源码分析(自己的,很详细)

Glide--LruCache源码分析(文章一:阅读量152,1赞)

LruCache原理和用法与LinkedHashMap(文章二:阅读量6472,7赞)

java容器类LinkedHashMap源码分析

1、源码分析:

LruCache算法,又称为近期最少使用算法。主要算法原理就是把最近所使用的对象的强引用存储在LinkedHashMap上,并且,把最近最少使用的对象在缓存池达到预设值之前从内存中移除。

Glide中LruCache的源码:

public class LruCache<T, Y> {private final LinkedHashMap<T, Y> cache = new LinkedHashMap<>(100, 0.75f, true);private final int initialMaxSize;private int maxSize;private int currentSize = 0;/*** Constructor for LruCache.** @param size The maximum size of the cache, the units must match the units used in {@link*             #getSize(Object)}.*/public LruCache(int size) {this.initialMaxSize = size;this.maxSize = size;}/*** Sets a size multiplier that will be applied to the size provided in the constructor to put the* new size of the cache. If the new size is less than the current size, entries will be evicted* until the current size is less than or equal to the new size.** @param multiplier The multiplier to apply.*/public synchronized void setSizeMultiplier(float multiplier) {if (multiplier < 0) {throw new IllegalArgumentException("Multiplier must be >= 0");}maxSize = Math.round(initialMaxSize * multiplier);evict();}/*** Returns the size of a given item, defaulting to one. The units must match those used in the* size passed in to the constructor. Subclasses can override this method to return sizes in* various units, usually bytes.** @param item The item to get the size of.*/protected int getSize(Y item) {return 1;}/*** A callback called whenever an item is evicted from the cache. Subclasses can override.** @param key  The key of the evicted item.* @param item The evicted item.*/protected void onItemEvicted(T key, Y item) {// optional override}/*** Returns the current maximum size of the cache in bytes.*/public synchronized int getMaxSize() {return maxSize;}/*** Returns the sum of the sizes of all items in the cache.*/public synchronized int getCurrentSize() {return currentSize;}/*** Returns true if there is a value for the given key in the cache.** @param key The key to check.*/public synchronized boolean contains(T key) {return cache.containsKey(key);}/*** Returns the item in the cache for the given key or null if no such item exists.** @param key The key to check.*/@Nullablepublic synchronized Y get(T key) {return cache.get(key);}/*** Adds the given item to the cache with the given key and returns any previous entry for the* given key that may have already been in the cache.** <p> If the size of the item is larger than the total cache size, the item will not be added to* the cache and instead {@link #onItemEvicted(Object, Object)} will be called synchronously with* the given key and item. </p>** @param key  The key to add the item at.* @param item The item to add.*/public synchronized Y put(T key, Y item) {final int itemSize = getSize(item);if (itemSize >= maxSize) {onItemEvicted(key, item);return null;}final Y result = cache.put(key, item);if (item != null) {currentSize += getSize(item);}if (result != null) {// TODO: should we call onItemEvicted here?currentSize -= getSize(result);}evict();return result;}/*** Removes the item at the given key and returns the removed item if present, and null otherwise.** @param key The key to remove the item at.*/@Nullablepublic synchronized Y remove(T key) {final Y value = cache.remove(key);if (value != null) {currentSize -= getSize(value);}return value;}/*** Clears all items in the cache.*/public void clearMemory() {trimToSize(0);}/*** Removes the least recently used items from the cache until the current size is less than the* given size.** @param size The size the cache should be less than.*/protected synchronized void trimToSize(int size) {Map.Entry<T, Y> last;while (currentSize > size) {last = cache.entrySet().iterator().next();final Y toRemove = last.getValue();currentSize -= getSize(toRemove);final T key = last.getKey();cache.remove(key);onItemEvicted(key, toRemove);}}private void evict() {trimToSize(maxSize);}
}

LruCache采用的集合是LinkedHashMap,这个集合是HashMap的基础上增加了 数据链表的功能,可以看到下面这个构造函数,第一个是初始容量100, 第二个是碰撞因子0.75(即真实容量到达总容量的75%就开始扩容),第三个是链表顺序是否按访问顺序,关于这个容器的代码分析我们放在下一篇文章,在这里我们只需要知道这个集合能记录到你访问数据的次序,最近的访问的会放在链表的前面

 private final LinkedHashMap<T, Y> cache = new LinkedHashMap<>(100, 0.75f, true);

initialMaxSize:初始大小,maxSize:最大,currentSize:当前 三个成员变量,创建时this.initialMaxSize 和this.maxSize 一样。 注意setSizeMultiplier函数的作用是传入一个变化乘数,改变当前的最大容量

 private final int initialMaxSize;private int maxSize;private int currentSize = 0;public LruCache(int size) {this.initialMaxSize = size;this.maxSize = size;}public synchronized void setSizeMultiplier(float multiplier) {if (multiplier < 0) {throw new IllegalArgumentException("Multiplier must be >= 0");}maxSize = Math.round(initialMaxSize * multiplier);evict();}

evict意思是驱逐,就是把数据清除出缓存,把容量缩减到小于等于maxSize,while循环,处理当前大小大于入参的情况,取出链表中的一个,获取其value的大小,清除,更新当前容器容量,直到符合要求

protected synchronized void trimToSize(int size) {Map.Entry<T, Y> last;while (currentSize > size) {last = cache.entrySet().iterator().next();final Y toRemove = last.getValue();currentSize -= getSize(toRemove);final T key = last.getKey();cache.remove(key);onItemEvicted(key, toRemove);}}private void evict() {trimToSize(maxSize);}

获取item的大小,默认现在是1 。比如要实现一个Bitmap 缓存是需要返回大小的,缓存的大小是取决于所有bitmap的总大小和,而不是总个数

protected int getSize(Y item) {return 1;
}

一个清除元素发生的回调,让LruCache 的继承者选择自己做要的事

  protected void onItemEvicted(T key, Y item) {// optional override}

常规操作不解释

  public synchronized int getMaxSize() {return maxSize;}public synchronized int getCurrentSize() {return currentSize;}public synchronized boolean contains(T key) {return cache.containsKey(key);}@Nullablepublic synchronized Y get(T key) {return cache.get(key);}

put操作,首先获取待加入的item 大小,如果大于缓存最大容量,就不放进去,直接调用onItemEvicte. 小于缓存最大容量,执行放入,item不为空,更新缓存当前大小。 执行放入的结果result就是说如果之前在容器内key存在,会执行替换value的操作,这时候result!=null,需要把替换出来的item的大小减去, 作者弄了个//TODO,不知道这里是否加上onItemEvicted 的回调,个人感觉应该加上,毕竟数据被清除缓存了,通知下,怎么处理交给继承者。 最后 evict(),因为单个待处理的item大小小于缓存最大容量,但是加入后,有可能超出,这里加个维护容量的代码

  public synchronized Y put(T key, Y item) {final int itemSize = getSize(item);if (itemSize >= maxSize) {onItemEvicted(key, item);return null;}final Y result = cache.put(key, item);if (item != null) {currentSize += getSize(item);}if (result != null) {// TODO: should we call onItemEvicted here?currentSize -= getSize(result);}evict();return result;}

清除key出缓存,常规操作,维护当前缓存大小

 public synchronized Y remove(T key) {final Y value = cache.remove(key);if (value != null) {currentSize -= getSize(value);}return value;}

让缓存容量小于等于0,起到clearMemory的作用

  public void clearMemory() {trimToSize(0);}

2、为什么用LinkedHashMap

LRUCache源码分析(自己的,很详细)

为什么要用LinkedHashMap来存缓存呢,这个跟算法有关,LinkedHashMap刚好能提供LRUCache需要的算法。

这个集合内部本来就有个排序功能,当第三个参数是true的时候,数据在被访问的时候就会排序,这个排序的结果就是把最近访问的数据放到集合的最后面。

到时候删除的时候就从前面开始删除。

LRUCache 原理相关推荐

  1. LruCache原理

    创建LruCache对象,重写其中的sizeOf方法: 然后看看LruCache内部长啥样子??? 看到A处,这里有个LinkedHashMap,这个是专门来存要缓存的对象,这个数据结构有个特点即链表 ...

  2. Android LRUCache原理

    关于Android的三级缓存,其中主要的就是内存缓存和硬盘缓存.这两种缓存机制的实现都应用到了LruCache算法,今天我们就从使用到源码解析,来彻底理解Android中的缓存机制. 一.Androi ...

  3. Android基础-LruCache原理解析

    一.Android中的缓存策略 一般来说,缓存策略主要包含缓存的添加.获取和删除这三类操作.如何添加和获取缓存这个比较好理解,那么为什么还要删除缓存呢?这是因为不管是内存缓存还是硬盘缓存,它们的缓存大 ...

  4. 浅析LruCache原理

    Android用LruCache来取代原来强引用和软引用实现内存缓存,因为据说自2.3以后Android将更频繁的调用GC,导致软引用缓存的数据极易被释放. LruCache使用一个LinkedHas ...

  5. java lrucache_Java LruCache 的使用及原理

    概述 LRU (Least Recently Used) 的意思就是近期最少使用算法,它的核心思想就是会优先淘汰那些近期最少使用的缓存对象. 在我们日常开发中,UI 界面进行网络图片加载是很正常的一件 ...

  6. Android开源框架源码鉴赏:LruCache与DiskLruCache

    关于作者 郭孝星,程序员,吉他手,主要从事Android平台基础架构方面的工作,欢迎交流技术方面的问题,可以去我的Github提issue或者发邮件至guoxiaoxingse@163.com与我交流 ...

  7. Android性能优化之启动优化实战篇,最新整理

    一.java面试题 熟练掌握java是很关键的,大公司不仅仅要求你会使用几个api,更多的是要你熟悉源码实现原理,甚至要你知道有哪些不足,怎么改进,还有一些java有关的一些算法,设计模式等等. (一 ...

  8. Android工程师面试该怎么准备?终局之战

    (一)简介 Handler机制是一套Android消息传递机制.在Android开发多线程的应用场景中,将工作线程中需更新UI的操作信息 传递到 UI主线程,从而实现 工作线程对UI的更新处理,最终实 ...

  9. 深入理解JVM文章合集

    原文地址:http://ddrv.cn/a/88331 Java动态追踪技术探究 在Java虚拟机中,字符串常量到底存放在哪 一次生产 CPU 100% 排查优化实践 聊聊 Java 虚拟机:类的加载 ...

最新文章

  1. NYOJ——街区最短路径问题
  2. china-pub计算机图书最新一周排行榜
  3. python项目2019_2019 年 11 月精选 GitHub 上 几个牛逼 Python 的项目
  4. 数据结构-单循环链表(C语言代码)
  5. JVM 调优实战--一个案例理解常用工具(命令)
  6. Spark 运行机制
  7. 基于matlab的频域辨识,基于Lab VIEW的控制系统频域分析研究
  8. 一个函数里两个setjmp_C语言中setjmp.h的longjmp()函数
  9. jmeter web监听结果_jmeter使用总结
  10. GBK转unicode码查询表
  11. Processing-基础小坑-
  12. java 关键字小结
  13. 移动端关于手机横屏时样式修改
  14. marlin 多轴电机驱动
  15. 洛谷P4234 最小差值生成树 题解
  16. 记录学习Android基础的心得07:硬件控制P2
  17. 视频去水印在线网站?
  18. java中的标号:outer的作用
  19. 很多男性的瘦腰细腿比女性更骨感?原因告诉你,或许他们真没减肥
  20. Jenkins凭据导出

热门文章

  1. 关于主板不支持SAS硬盘求解大佬
  2. 触摸按键设计layout
  3. 赛迪顾问 | 政府大数据行业深度解读
  4. Python 确定大图中是否包含小图
  5. book_shop 实验十
  6. 企业业务架构的需求管理与软件开发的供求曲线
  7. 龙芯处理器是否可以运行windows操作系统
  8. nginx - ip 限制规则、黑名单、白名单
  9. CSS——灵活布局 float (浮动属性)
  10. 手把手教你如何设计打地鼠游戏(技术教程)