首页 > 编程知识 正文

dir /b命令,oom解决方法

时间:2023-05-04 20:22:23 阅读:135034 作者:4396

简介LruCache是安卓3.1的时候出来的。 一般来说,为了与低版本的兼容性,我们使用v4包。 LruCache是一种缓存策略,它具有很强的引用,但会被限制在峰值。 内部管理队列,每次从队列中检索值时,该值都会移动到队列的开头。 当缓存已满并继续添加时,队列末尾的值将被删除,从而有助于GC。 LruCache用于内存缓存,在避免程序OOM的发生和提高执行效率方面很有优势。

LRU算法与名称相同,LruCache的实现正是基于LRU(Least Recently Used )算法。 最近的最低使用,我理解的是,最老的最低使用会先被淘汰。 下图显示了LRU算法的核心思想,是最常用、比较简单的:

假设队列的最大容量为5,则会将新添加的元素添加到头部,并在队列已满时删除尾部元素。 值得注意的是,不在队列开头的元素c再次插入队列时。 如果队列中已经存在c,请将c元素移动到开头,而不是重复插入。 这相当于其存在的优先顺序是目前最高的。

链接hashmap通过查看LruCache的源代码很容易发现。 只有一个容器类,链接hashmap。 正好LinkedHashMap是双向链表的数据结构,分为访问顺序和插入顺序。 LruCache只提供了一个带参数的构造函数:

publiclrucache(intmaxsize ) if ) maxsize=0) thrownewillegalargumentexception ) ' maxsize=0' ); } this.maxSize=maxSize; this.map=new LinkedHashMapK,v (0,0.75 f,true ); }这里初始化了LinkedHashMap,按照访问顺序进行了排序。 也就是说,遍历队列的entrySet,最初的输出总是最先被插入,最近没有被访问(操作)。 最后访问的元素总是作为团队的最后一个输出。 请注意此处开头团队的末尾,以及LruCache描述的队列和上图中队列之间的差异。 很容易骗人。

LruCache初始化以下是一些比较重要的成员变量和代表的意思:

私有大小; //当前缓存的大小private int maxSize; //最xydjd缓存的大小private int hitCount; //命中缓存的次数private int missCount; //在缓存丢失次数为LruCache的构造函数中传递的参数将以最大缓存容量分配给maxSize。 如果在初始化此LruCache对象时没有重写sizeOf方法,则maxSize表示内部LinkedHashMap可以存储的最大键值对数量。 sizeOf缺省返回1,这意味着生产了键-值对。 注意只有maxSize和sizeOf的返回值是相同的单位制缓存的判断才有意义。

put LruCache如何插入元素(缓存值) :

publicfinalvput(kkey,V value ) if ) key==null||value==null ) thrownewnullpointerexception (' key==null|) v 同步(this ) { putCount; size=safesizeof(key,value ); previous=map.put(key,value ); 特权!=null ) {size-=safesizeof(key,previous ); } if (权限!=null (实体移除(value,key,previous,value ) ); }trimtosize(maxsize; 返回权限; }异常判断表示LruCache不允许进行键或值为空的操作。 前面说过,在插入元素之前,将调用一次sizeOf,缺省值返回1,但一般会根据实际需要进行重写。 例如,如果用LruCache保存的value为File,则sizeOf当前应该返回与key对应的文件大小。 对应的size也必须完成自我成长。 这是因为当前缓存增加,相应的key-value已插入链表中。 在二次检查中,如果此key已经存在于链表中,此时新的value被覆盖后,size将减去以前的value占用的大小。 以上操作均已同步。 为了保证多线程场景中size的正确性,否则将禁用缓存策略。 如果覆盖旧的value,则LruCache为外部提供了一种空的方法entryRemoved。 调用trimToSize以防止缓存溢出。 trimtosizepublicvoidtrimtosize (int maxsize ) while ) true ) { K key; V value; 同步(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); }}

该方法每插入一次元素就会被调用一次。整个方法就是一个无限循环,判断当前缓存大小不大于最大容量则结束循环。否则就取出LinkedHashMap的entrySet的头部,也就是最早被插入且最近未被访问过的键值对并删除,更新size。重复此步骤直到缓存<=最大容量。不得不说利用访问顺序的LinkedHashMap的特性完成LRU缓存,非常巧妙。

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++; } /* * Attempt to create a value. This may take a long time, and the map * may be different when create() returns. If a conflicting value was * added to the map while create() was working, we leave that value in * the map and release the created value. */ 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; }} key不可以为null如果map中存在与key相对应的value,则返回该value,并且缓存命中数+1。不存在,则缓存丢失数+1不存在的话会尝试根据该key创建一个value。创建方法默认返回null,需要自己实现。 其它

除此之外,LruCache还提供了手动清除指定缓存remove(K key),清除所有缓存evictAll()等方法供使用者调用。弄明白LinkedHashMap就很容易弄懂LruCache的实现了。

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。