Skip to content

2019-06-19:简要说说 LruCache 的原理? #79

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
Moosphan opened this issue Jun 19, 2019 · 9 comments
Open

2019-06-19:简要说说 LruCache 的原理? #79

Moosphan opened this issue Jun 19, 2019 · 9 comments

Comments

@Moosphan
Copy link
Owner

No description provided.

@gabyallen
Copy link

LruCache是使用一个LinkedHashMap简单内存的缓存,是强引用;没有软引用。如果添加的数据大于设置的数据,就删除最先缓存数据来调整内存数据。
maxside数据是初始化的时候构造函数设置最大值。表示能够缓存最大数据。

@guosen
Copy link

guosen commented Jun 19, 2019

LRU 顾名思义就是最近最少使用,才用链表实现

@18361237136
Copy link

LruCache是最近最少使用算法
是用LinkedHashMap实现的简单的内存的缓存,是强引用。
如果添加的数据大于设置的最大的缓存数据,就删除最先缓存的或不使用的数据来调整内存。

@LvKang-insist
Copy link

LruCache 非常适合用于 缓存图片,他的主要算法原理是包最近使用的对象 存储在 LinckHashMap中,并且把最近使用的最少的对象在 缓存值达到预设值之前从内存中移除

`public class LruCachePhoto {
/**
* 图片 缓存技术的核心类,用于缓存下载好的所有图片,
* 在程序内存达到设定值后会将最少最近使用的图片移除掉
*/
private LruCache<String, Bitmap> mMenoryCache;

public LruCachePhoto() {
    //获取应用最大可用内存
    int maxMemory = (int) Runtime.getRuntime().maxMemory();
    //设置 缓存文件大小为 程序最大可用内存的 1/8
    int cacheSize = maxMemory / 8;

    mMenoryCache = new LruCache<String, Bitmap>(cacheSize) {
        @Override
        protected int sizeOf(String key, Bitmap value) {
            return value.getByteCount();
        }
    };
}

/**
 * 从 LruCache 中获取一张图片,如果不存在 就返回 null
 *
 * @param key LurCache 的键,这里是 图片的地址
 * @return 返回对应的 Bitmap对象,找不到则为 null
 */
public Bitmap getBitmapFromMemoryCache(String key) {
    return mMenoryCache.get(key);
}

/**
 * 添加一张图片
 *
 * @param key    key
 * @param bitmap bitmap
 */
public void addBitmapToCache(String key, Bitmap bitmap) {
    if (getBitmapFromMemoryCache(key) == null) {
        mMenoryCache.put(key, bitmap);
    }
}

}`

@Alex-Cin
Copy link

Alex-Cin commented Aug 2, 2019

androidx.collection.LruCache
初始化的时候, 会限制缓存占据内存空间的总容量 maxSize;
底层维护的是 LinkedHashMap, 使用 LruCache 最好要重写 sizeOf 方法, 用于计算每个被缓存的对象, 在内存中存储时, 占用多少空间;

在 put 操作时, 首先计算新的缓存对象, 占多少空间, 再根据 key, 移除老的对象,
占用内存大小 = 之前占用的内存大小 + 新对象的大小 - 老对象的大小;
put 操作最后总会根据 maxSize, 在拿到 LinkedHashMap.EntrySet 中链表的头节点, 循环判断, 只要当前缓存对象占据内存超出 maxSize, 就移除一个头节点, 一直到符合要求;

lruCache 和 LinkedHashMap 的关系:
LinkedHashMap 中维护一个双向链表, 并维护 head 和 tail 指针, lruCache 使用了 LinkedHashMap accessOrder 为 true 的属性, 只要访问了某个 key,
包括 get 和 put, 就把当前这个 entry 放在链表的位节点, 所以链表的头节点, 是最老访问的节点, 尾节点是最新访问的节点,
所以, lruCache 就很巧妙的利用了这个特点, 完成了 Least Recently Used 的需求;

@MrCodeSniper
Copy link

LruCache和DiskLruCache底层实现

LRU概念-最近最少使用 将访问的元素根据访问的顺序 进行排序

LruCache和DiskLruCache底层均为LinkedHashMap 是一个由包含KV的结点形成的双向链表

按照进入的顺序排列 当进入的元素在链表里有重复 会将这个元素调到链头表示访问频度高 当超过空间阈值时 会首先淘汰最近最少使用的元素

DiskLru相比于Lru来说 更注重于对文件的读写 和文件操作的保护

LruCache因为其特性会出现在使用中有元素被淘汰 而在业务场景中有时候需要被淘汰的元素 我们可以将其淘汰的元素 存储起来保存在队列中 避免这种情况

@huazidev
Copy link

huazidev commented Jun 17, 2020

LruCache 是最近最少使用算法的一种实现,主要用于内存缓存。

LruCache 内部使用 LinkedHashMap 来实现最近最少使用的核心逻辑。通过构造函数初始化最大的cache 大小,其单位要和 sizeOf 大小一致。还会初始化一个有序的 LinkedHashMap,这个 LinkedHashMap 是个有序的双向链表,根据进入顺序进行排序,新进入或最新使用的放在链表尾部,这样表头就是最少使用的。当超过给定的大小时就会移除表头的数据,知道大小小于给定大小为止。

注意:LruCache 是强引用,LruCache 本身并没有释放内存存,它只是把 LinkedHashMap 中的数据移除,如果数据还在其他地方引用,还是无法释放内存,可以手动释放;

@mlinqirong
Copy link

LruCache 是android 提供的缓存类 内部提供了LinkedHashMap来做存储方式 而LinkedHashMap持有对象是以强引用的方式,所以不会被系统回收掉。
在创建的时候给LruCache 指定最大的存储空间 并创建初始量为0的LinkedHashMap来存储对象 重写sizeOf返回存储对象所占用的空间 指定存储空间满了之后 会移动最近最少使用的存储对象

1 similar comment
@mlinqirong
Copy link

LruCache 是android 提供的缓存类 内部提供了LinkedHashMap来做存储方式 而LinkedHashMap持有对象是以强引用的方式,所以不会被系统回收掉。
在创建的时候给LruCache 指定最大的存储空间 并创建初始量为0的LinkedHashMap来存储对象 重写sizeOf返回存储对象所占用的空间 指定存储空间满了之后 会移动最近最少使用的存储对象

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

9 participants