美文网首页
LruCache分析

LruCache分析

作者: 波波维奇c | 来源:发表于2018-02-04 15:06 被阅读0次

LruCache:

LruCache是个泛型类,主要算法原理是把最近使用的对象用强引用(即我们平常使
用的对象引用方式)存储在 LinkedHashMap 中。当缓存满时,把最近最少使用的
对象从内存中移除,并提供了get和put方法来完成缓存的获取和添加操作。

强引用:直接对象的引用
弱引用:当一个对象只有一个弱引用存在时,此对象随时会被GC回收
软引用:当一个对象只有一个软引用存在时,当系统内存不足时,会被GC回收

LruCache使用:

 //获取系统内存
 int maxMemory = (int) (Runtime.getRuntime().totalMemory() / 1024);
       //设置缓存内存为系统内存的1/8
       int cacheSize=maxMemory/8;
        LruCache<String,Bitmap> lruCache = new LruCache<String,Bitmap>(cacheSize){
            @Override
            protected int sizeOf(String key, Bitmap value) {
                return value.getRowBytes()*value.getHeight()/1024;
            }
        };

这段代码主要是确定LruCache的缓存大小,重写SizeOf是确定图片的大小。(单位要统一)

原理:

LruCache的核心就是维护一个缓存对象列表,其中列表对象的缓存排序为顺序排序,就是一直没访问的对象,将放在队尾,即将被淘汰。而最近访问的对象将放在队头,最后被淘汰。而这个队列是由LinkHashMap来维护的,它是一个数组+双向链表的数据结构来实现的。其中双向链表的结构可以实现访问顺序和插入顺序。这样的特性可以让LinkHashMap可以实现顺序排序。

分析LinkHashMap:看一下LinkHashMap的构造函数

 public LinkedHashMap(int initialCapacity,
                         float loadFactor,
                         boolean accessOrder) {
        super(initialCapacity, loadFactor);
        this.accessOrder = accessOrder;
        }

其中当参数 accessOrder=true,为排序,为false时为插叙。
那么LinkHaspMap,又是如何添加,获取还有删除的?
看下LruCache的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;
    }

看一下 trimToSize()方法:

  public void trimToSize(int maxSize) {
        while (true) {
            K key;
            V value;
            synchronized (this) {
    //如果map为空并且缓存size不等于0或者缓存size小于0,抛出异常
                if (size < 0 || (map.isEmpty() && size != 0)) {
                    throw new IllegalStateException(getClass().getName()
                            + ".sizeOf() is reporting inconsistent results!");
                }

                if (size <= maxSize) {
                    break;
                }
                //若如果超过缓存的操作
                Map.Entry<K, V> toEvict = map.eldest();
                if (toEvict == null) {
                    break;
                }
            //获取最先访问的键值对,并且移除和回收资源
                key = toEvict.getKey();
                value = toEvict.getValue();
                map.remove(key);
                size -= safeSizeOf(key, value);
                evictionCount++;
            }
          //回收资源
            entryRemoved(true, key, value, null);
        }
    }

trimToSize()方法,就是一添加就会去循环判断缓存是否已满,不满则跳出循环,否则就删除最先访问的对象。
看一下get方法:

    public final V get(K key) {
    //判断
        if (key == null) {
            throw new NullPointerException("key == null");
        }

        V mapValue;
        synchronized (this) {
           //获取缓存对象,在get方法里面会把最近访问的放在头部
            mapValue = map.get(key);
            if (mapValue != null) {
                hitCount++;
                return mapValue;
            }
            missCount++;
        }

点进去get();

public V get(Object key) {
        Node<K,V> e;
        if ((e = getNode(hash(key), key)) == null)
            return null;
            //排序
        if (accessOrder)
            afterNodeAccess(e);
        return e.value;
    }

由此可见LruCache中维护了一个集合LinkedHashMap,该LinkedHashMap是以
访问顺序排序的。当调用put()方法时,就会在结合中添加元素,并调用
trimToSize()判断缓存是否已满,如果满了就用LinkedHashMap的迭代器删除队尾
元素,即近期最少访问的元素。当调用get()方法访问缓存对象时,就会调用
LinkedHashMap的get()方法获得对应集合元素,同时会更新该元素到队头。

相关文章

  • Android-Glide源码解析

    一、LruCache 要分析Glide的源码,首先就需要分析LruCache。LruCache是基于LinkedH...

  • 缓存分析

    LruCache与DiskLruCache 文章目录 一 Lru算法 二 LruCache原理分析2.1 写入缓存...

  • LruCache之LruCache分析

    LruCache 分析 LruCache 是 Android 的一个内部类,提供了基于内存实现的缓存 用法 源码 ...

  • Android cache缓存

    Android 缓存机制 LruCache缓存机制分析

  • LruCache分析

    LruCache: LruCache是个泛型类,主要算法原理是把最近使用的对象用强引用(即我们平常使用的对象引用方...

  • LruCache

    文章主要介绍了:1.LruCache的基本使用2.LruCache的源码分析3.基于LinkedHashMap的实...

  • LruCache源码解析

    分析的LurCache来自于开源库picasso。一、LruCache初始化 LruCache初始化很简单,只用传...

  • LruCache源码分析

    LruCache类里面有一个LinkedHashMap map的变量,缓存主要就是用这个map来做的,l...

  • 源码分析 LruCache

    简介 为什么用 一个app持有的内存是有限的,无限制的使用强引用在内存中缓存数据,有可能导致OOM。 能做什么 L...

  • LruCache源码分析

    在开发中我们会经常碰到一些资源需要做缓存优化,例如Bitmap,Json等,那么今天我们来瞧瞧默默无闻的LruCa...

网友评论

      本文标题:LruCache分析

      本文链接:https://www.haomeiwen.com/subject/fgmmzxtx.html