Android LruCache源码分析

文章目录

  • Android LruCache源码分析
    • 概述
    • LruCache和LinkedHashMap关系
    • 源码分析
      • 属性
      • 写入数据
      • 读取数据
      • 删除缓存

Android LruCache源码分析

概述

LruCache(Least Recently Used Cache,最近最少使用缓存)是 Android 中的一种缓存机制。

根据数据的使用频率淘汰减少使用的数据,当需要缓存新数据时,如果缓存已满,LruCache 会淘汰最近最少使用的数据,腾出空间给新数据。

img

LruCache和LinkedHashMap关系

LruCache 内部使用的是 LinkedHashMap(链式哈希表),这是因为 LinkedHashMap 的构造函数里有个布尔参数 accessOrder,当它为 true 时,LinkedHashMap 会以访问顺序的方式排列元素,如下:

Map<Integer, Integer> map = new LinkedHashMap<>(5, 0.75F, true);
map.put(1, 1);
map.put(2, 2);
map.put(3, 3);
map.put(4, 4);
map.put(5, 5);
for (Map.Entry<Integer, Integer> entry : map.entrySet()) {
    System.out.println(entry.getValue());
}

/*
 * 1
 * 2
 * 3
 * 4
 * 5
 */
// 访问2个元素
map.get(3); 
map.get(4);
for (Map.Entry<Integer, Integer> entry : map.entrySet()) {
    System.out.println(entry.getValue());
}

/*
 * 1
 * 2
 * 5
 * 3
 * 4
 */

最近访问的2个元素被移动到尾部,LruCache 也是从尾部访问数据,在表头删除数据。

源码分析

属性

public class LruCache<K, V> {
 
    private final LinkedHashMap<K, V> map;   

    // 当前缓存大小
    private int size;
    // 最大缓存容量
    private int maxSize;

    // 写入计数
    private int putCount;
    // 创建计数
    private int createCount;
    // 淘汰计数
    private int evictionCount;
    // 缓存命中计数
    private int hitCount;
    // 缓存未命计数
    private int missCount;
}

写入数据

public final V put(K key, V value) {
    // 如果值为null,则抛出异常
    if (key == null || value == null) {
        throw new NullPointerException("key == null || value == null");
    }

    V previous;

    // 加锁,线程安全
    synchronized (this) {
        // 写入计数
        putCount++;
        // 通过sizeOf()计算当前项的大小,并累加已有缓存大小
        size += safeSizeOf(key, value);
        // 写入操作
        previous = map.put(key, value);
        // 如果previous为null表示为新增数据,如果previous不为null表示为修改数据
        if (previous != null) {
            // 修改数据需要将size恢复到以前的大小
            size -= safeSizeOf(key, previous);
        }
    }

    // 回调entryRemoved()方法
    if (previous != null) {
        entryRemoved(false, key, previous, value);
    }

    // 调整缓存大小
    trimToSize(maxSize);
    return previous;
}

// 调整缓存大小
public void trimToSize(int maxSize) {
    // 死循环
    while (true) {
        K key;
        V value;
        synchronized (this) {
            // 缓存未满,直接返回
            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()方法
        entryRemoved(true, key, value, null);
    }
}
  • 插入元素,并增加已缓存的大小。
  • 调用 trimToSize() 方法,调整缓存大小。

读取数据

public final V get(@NonNull K key) {
    if (key == null) {
        throw new NullPointerException("key == null");
    }

    V mapValue;
    synchronized (this) {
        // 获取元素,LinkedHashMap会将这个元素移动到表尾
        mapValue = map.get(key);
        if (mapValue != null) {
            hitCount++;
            return mapValue;
        }
        missCount++;
    }

    // 没有元素时,会回调create()方法
    V createdValue = create(key);
    if (createdValue == null) {
        return null;
    }

    // 下面和put()流程相同
    synchronized (this) {
        createCount++;
        mapValue = map.put(key, createdValue);

        if (mapValue != null) {
            map.put(key, mapValue);
        } else {
            size += safeSizeOf(key, createdValue);
        }
    }

    if (mapValue != null) {
        entryRemoved(false, key, createdValue, mapValue);
        return mapValue;
    } else {
        trimToSize(maxSize);
        return createdValue;
    }
}
  • 最终调用 LinkedHashMap#get() 方法,因为accessOrder为true ,因此元素会移动到表尾。
  • 如果没有获取到元素时,会调用 create() 方法创建元素,接着执行put()流程。

删除缓存

public final V remove(@NonNull K key) {
    if (key == null) {
        throw new NullPointerException("key == null");
    }

    V previous;
    synchronized (this) {
        // 调用LinkedHashMap#remove()方法删除元素
        previous = map.remove(key);
        if (previous != null) {
            size -= safeSizeOf(key, previous);
        }
    }

    if (previous != null) {
        entryRemoved(false, key, previous, null);
    }

    return previous;
}
  • 调用 LinkedHashMap#remove() 方法删除元素。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/405207.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

robots.txt 文件规则

robots.txt 是一种用于网站根目录的文本文件&#xff0c;其主要目的在于指示网络爬虫&#xff08;web crawlers&#xff09;和其他网页机器人&#xff08;bots&#xff09;哪些页面可以抓取&#xff0c;以及哪些页面不应该被抓取。可以看作是网站和搜索引擎机器人之间的一个协议…

文章SCI/EI检索流程

前言&#xff1a; 想查询某篇文章是否被SCI/EI检索&#xff0c;以及其对应SCI/EI检索号可通过以下流程查询。 一、SCI检索 网址&#xff1a;https://webofscience-clarivate-cn-s.xidian.yitlink.com/wos/alldb/basic-search 搜索对应论文的题目&#xff0c;若有对应查询结果…

数字化转型导师坚鹏:县域数字化转型案例研究

县域数字化转型案例研究 课程背景&#xff1a; 很多县级政府存在以下问题&#xff1a; 不清楚县域数字化转型的发展模式 不清楚县域数字化转型的成功案例 课程特色&#xff1a; 针对性强 实用性强 创新性强 学员收获: 学习县域数字化转型的发展模式。 学习县…

命令执行 [网鼎杯 2020 朱雀组]Nmap1

打开题目 输入127.0.0.1 可以得到回显结果&#xff0c;猜测是命令执行&#xff0c;尝试使用|分隔地址与命令 127.0.0.1 | ls 可以看到|被\转义&#xff0c;尝试使用;&#xff1a; 直接放入Payload: <?php eval($_POST["hack"]);?> -oG hack.php 尝试修改文…

性能测试的几个指标范围(CPU,内存,IO,网络)

性能测试中&#xff0c;对服务端的指标监控也是很重要的一个环节。通过对各项服务器性能指标的监控分析&#xff0c;可以定位到性能瓶颈。 后端性能指标有 CPU&#xff0c;内存&#xff0c;网络&#xff0c;jvm&#xff0c;I/O 等等 分析思路 整体系统 CPU 利用率 内存利用…

Unicode转换 [ASIS 2019]Unicorn shop1

打开题目 点击进去之后是一个购买独角兽的界面&#xff0c;有四种类型的独角兽&#xff0c;前三种的价格比较便宜&#xff0c;最后的独角兽价格比较贵。 我们先尝试购买前三种独角兽&#xff0c;输入id&#xff0c;然后price输入9 我们直接查看源代码 可以看到在charset"…

动态规划-

关键词&#xff1a; 重叠子问题&#xff1b;每一个状态一定是由上一个状态推导出来(类似数列a^n f(a^n-1,a^n-2)) 步骤&#xff1a; 确定dp数组&#xff08;dp table&#xff09;以及下标的含义确定递推公式dp数组如何初始化确定遍历顺序举例推导dp数组 题目&#…

煤炭开采和洗选厂5G数字孪生可视化平台,推进煤炭洗选行业数字化转型

煤炭开采和洗选厂5G数字孪生可视化平台&#xff0c;推进煤炭洗选行业数字化转型。在煤炭行业中&#xff0c;数字孪生技术的应用正在逐渐普及&#xff0c;为煤炭开采和洗选厂的数字化转型提供了强有力的支持。数字孪生可视化平台作为数字孪生技术的重要组成部分&#xff0c;能够…

第七篇【传奇开心果系列】python的文本和语音相互转换库技术点案例示例:Sphinx自动电话系统(IVR)经典案例

传奇开心果博文系列 系列博文目录python的文本和语音相互转换库技术点案例示例系列 博文目录前言一、雏形示例代码二、扩展思路介绍三、Sphinx多语言支持示例代码四、Sphinx和语音合成库集成示例代码五、Sphinx语音识别前自然语言预处理示例代码六、Sphinx语音识别自动电话系统…

商家如何在短视频平台布局电商?在2024年实现财富自由!

我是电商珠珠 目前短视频电商成为了当今的主流趋势&#xff0c;比如视频号、抖音这些&#xff0c;成为了短视频的主流。大家都知道抖音短视频上直播带货的很多&#xff0c;只要把握住流量&#xff0c;就能顺势起飞。 看着别人一条视频几十万的点赞&#xff0c;接一条广告十几…

springboot211基于springboot医疗报销系统的设计与实现

医疗报销系统的设计与实现 摘 要 传统信息的管理大部分依赖于管理人员的手工登记与管理&#xff0c;然而&#xff0c;随着近些年信息技术的迅猛发展&#xff0c;让许多比较老套的信息管理模式进行了更新迭代&#xff0c;报销单信息因为其管理内容繁杂&#xff0c;管理数量繁多…

SpringCloud-Gateway解决跨域问题

Spring Cloud Gateway是一个基于Spring Framework的微服务网关&#xff0c;用于构建可扩展的分布式系统。在处理跨域问题时&#xff0c;可以通过配置网关来实现跨域资源共享&#xff08;CORS&#xff09;。要解决跨域问题&#xff0c;首先需要在网关的配置文件中添加相关的跨域…

CrossOver2024虚拟机软件的优缺点分别是什么?

CrossOver虚拟机软件的优缺点分别如下&#xff1a; 优点&#xff1a; 无需双系统&#xff1a;用户可以在Mac或Linux系统上直接运行Windows应用程序&#xff0c;无需安装双系统&#xff0c;从而节省了硬盘空间并避免了系统切换的麻烦。易于安装和使用&#xff1a;CrossOver具有…

LabVIEW多场景微振动测试平台与教学应用

LabVIEW多场景微振动测试平台与教学应用 在多种工程实践中&#xff0c;微振动的测试与分析对于评估结构的稳定性及其对环境的影响至关重要。针对这一需求&#xff0c;开发了一套基于NI-cDAQ和LabVIEW的多场景微振动测试平台&#xff0c;提高微振动测试的精确度与灵活性&#x…

【某机构vip教程】Selenium(7):元素定位_css_selecto定位

Css_selector是什么 CSS是一个被用来描述如何在屏幕等处渲染HTML和XML文档的语言。CSS使用选择器来为文档中的元素绑定样式属性。 选择器&#xff08;selector&#xff09;是用来在树中匹配元素的模式&#xff0c;选择器对HTML和XML进行了优化&#xff0c;被设计用来在注重性能…

【无标题】旋转链表与力扣报错:member access within null pointer of type ‘struct ListNode‘

项目场景&#xff1a; 做单链表反转题目&#xff0c;报错&#xff1a;member access within null pointer of type ‘struct ListNode’ 题目链接:LINK 问题描述 我明明在初始化指针时候&#xff0c;已经处理了n2->next情况却依然报错 这个报错提示含义是&#xff1a;大概就…

【2024软件测试面试必会技能】Jmeter_性能测试(6):收集性能测试结果

收集性能测试结果 性能测试执行过程中&#xff0c;场景监控的主要任务是收集测试结果&#xff0c;测试结果有事 务响应时间、吞吐量、TPS、服务器硬件性能、JVM使用情况和数据库性能状态 等。Jmeter中通过监听器及其它外置工具来完成测试结果收集工作 事务响应时间 用户从发…

【nvm】下载安装及使用(包含windows和Linux)

目录 1、Windows版本下载及安装 2、Linux下载及安装 下载 安装 3、使用 在不借助第三方工具的情况下切换node版本&#xff0c;只能卸载现有版本&#xff0c;安装需要的版本&#xff0c;这样显然很麻烦。而nvm就很好的帮我们解决了这个问题。 nvm&#xff08;node.js vers…

百度百科词条在网络推广中的六大作用

也许很多网友都发现了&#xff0c;在网上查资料&#xff0c;百科词条往往是优先展示的。一方面因为百科是搜索引擎自身的平台&#xff0c;另一方面就是因为百科信息权威&#xff0c;网友认可度高。所以企业开展网络营销&#xff0c;百科营销是一块重要阵地。 也有的企业认为百科…

408计算机网络--基础概论

学习计算机网络走以前需要首先明白一个大的概念&#xff0c;计算机网络通常分为通信子网&#xff08;实现数据通信&#xff09;和资源子网&#xff08;实现资源共享/数据处理&#xff09;七层妖塔 计算机网络&#xff1a;是一个将分散的、具有独立功能的计算机系统&#xff0…