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() 方法刪除元素。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/697136.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/697136.shtml
英文地址,請注明出處:http://en.pswp.cn/news/697136.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

MySQL 索引原理以及 SQL 優化

索引 索引&#xff1a;一種有序的存儲結構&#xff0c;按照單個或者多個列的值進行排序。索引的目的&#xff1a;提升搜索效率。索引分類&#xff1a; 數據結構 B 樹索引&#xff08;映射的是磁盤數據&#xff09;hash 索引&#xff08;快速鎖定內存數據&#xff09;全文索引 …

Day13-Linux系統用戶管理知識精講2

Day13-Linux系統用戶管理知識精講2 1. passwd 給用戶設置密碼2. chpasswd 批量設置密碼3. chage 查看和更改密碼屬性 更改用戶密碼過期信息4. 用戶組相關的命令了解 1. passwd 給用戶設置密碼 用戶自己給自己設置密碼直接passwd root用戶給普通用戶設置密碼passwd 用戶名。 …

ChatGPT調教指南 | 咒語指南 | Prompts提示詞教程(一)

在我們開始探索人工智能的世界時&#xff0c;了解如何與之有效沉浸交流是至關重要的。想象一下&#xff0c;你手中有一把鑰匙&#xff0c;可以解鎖與OpenAI的GPT模型溝通的無限可能。這把鑰匙就是——正確的提示詞&#xff08;prompts&#xff09;。無論你是AI領域的新手&#…

JS 筆記 --持續更新

this 指向調用 this 是執行上下文中的一個屬性&#xff0c;它指向最后一次調用這個方法的對象。 Function.apply(obj,args)方法能接收兩個參數 obj&#xff1a;這個對象將代替Function類里this對象 args&#xff1a;這個是數組&#xff0c;它將作為參數傳給Function&#xff08…

SpringCloud全家桶---常用微服務組件(1)

注冊中心: *作用: 服務管理 Eureka(不推薦)[讀音: 優瑞卡] Nacos(推薦) Zookeeper [讀音: 如k波] Consul [讀音:康壽] **注冊中心的核心功能原理(nacos)** 服務注冊: 當服務啟動時,會通過rest接口請求的方式向Nacos注冊自己的服務 服務心跳: NacosClient 會維護一個定時心跳持…

Sora背后的論文(1):使用 lstms 對視頻展現進行無監督學習

之前那篇《Sora背后的32篇論文》發出后&#xff0c;大家都覺得不錯&#xff0c;有很多小伙伴都開始啃論文了。 那么我就趁熱打鐵&#xff0c;把這32篇論文的通俗解讀版貼一下。 從去年開始&#xff0c;我基本上形成了一個思維方式&#xff0c;任何事情做之前先看看 有沒有好的…

個人博客系列-環境配置-gitee(2)

注冊gitee賬戶 地址&#xff1a;https://gitee.com/ 此步驟省略 新建倉庫 執行以下命令 即可 拉取代碼 創建目錄 mkdir myCode && cd myCode 登錄gitee找到項目&#xff0c;點擊克隆&#xff0c;拉取代碼 連接遠程倉庫命令 git remote add origin 倉庫地址http…

MariaDB落幕和思考

聽過MySQL的基本也都知道 MariaDB。MariaDB由MySQL的創始人主導開發&#xff0c;他早前曾以10億美元的價格&#xff0c;將自己創建的公司MySQL AB賣給了SUN&#xff0c;此后&#xff0c;隨著SUN被甲骨文收購&#xff0c;MySQL的所有權也落入Oracle的手中。傳聞MySQL的創始人擔心…

創建型設計模式 - 原型設計模式 - JAVA

原型設計模式 一 .簡介二. 案例三. 補充知識 前言 這是我在這個網站整理的筆記,有錯誤的地方請指出&#xff0c;關注我&#xff0c;接下來還會持續更新。 作者&#xff1a;神的孩子都在歌唱 一 .簡介 原型模式提供了一種機制&#xff0c;可以將原始對象復制到新對象&#xff0…

[TCP] TCP/IP 基礎知識詞典(2)

我想統計一下&#xff0c;TCP/IP 尤其是TCP協議&#xff0c;能搜到的常見的問題&#xff0c;整理起來&#xff0c;關鍵詞添加在目錄中&#xff0c;便于以后查閱。 目前預計整理共3篇&#xff1a; [TCP] TCP/IP 基礎知識問答 &#xff1a;基礎知識 [TCP] TCP/IP 基礎知識問答&…

游戲平臺如何定制開發?

隨著科技的飛速發展和互聯網的普及&#xff0c;游戲平臺已成為人們休閑娛樂的重要選擇。為了滿足用戶多樣化的需求&#xff0c;游戲平臺的定制開發顯得尤為重要。本文將探討游戲平臺定制開發的過程、關鍵要素以及注意事項&#xff0c;為有志于涉足此領域的開發者提供參考。 一、…

python opencv繪制圖像輪廓

目錄 一:查找繪制輪廓 二:計算圖像的矩特征 三:計算Hu矩

ApexRBp在線粒子傳感器在電動汽車電池制造的應用

電動汽車電池的崛起與顆粒污染的挑戰 隨著電動汽車&#xff08;EV&#xff09;市場的迅速擴張&#xff0c;對高性能鋰離子電池的需求也急劇增加。這些電池不僅是EV的心臟&#xff0c;更是推動其前行的核心動力。然而&#xff0c;在電池制造的每一個環節&#xff0c;都需要對多…

【Python筆記-設計模式】適配器模式

一、說明 適配器模式是一種結構型模式&#xff0c;它使接口不兼容的對象能夠相互合作 (一) 解決問題 主要解決接口不兼容問題 (二) 使用場景 當系統需要使用現有的類&#xff0c;但類的接口不符合需求時當需要一個統一的輸出接口&#xff0c;但輸入類型不可預知時當需要創…

查詢數據庫的編碼集Oracle,MySQL

1、查詢數據庫的編碼集Oracle,MySQL 1.1、oracle select * from v$nls_parameters where parameterNLS_CHARACTERSET; 查詢版本&#xff1a;SELECT * FROM v$version 2、MySQL編碼集 SELECT DEFAULT_CHARACTER_SET_NAME, DEFAULT_COLLATION_NAME FROM information_schema.SC…

【了解機器學習的定義與發展歷程】

曾夢想執劍走天涯&#xff0c;我是程序猿【AK】 目錄 簡述概要知識圖譜 簡述概要 了解機器學習的定義與發展歷程 知識圖譜 機器學習&#xff08;Machine Learning&#xff0c;ML&#xff09;是一門跨學科的學科&#xff0c;它使用計算機模擬或實現人類學習行為&#xff0c;通…

路由器的端口映射如何設置?

路由器的端口映射設置是網絡連接中常用的配置功能&#xff0c;通過將外部網絡訪問請求映射到內部設備&#xff0c;實現局域網內設備的遠程訪問。本文將介紹如何進行路由器的端口映射設置&#xff0c;并以【天聯】組網產品為例進行說明。 【天聯】組網產品介紹 【天聯】組網是一…

css3d制作正方體

使用css3d技術 &#xff0c;制作一個可以動態動畫的正方體模型 效果圖&#xff1a; 代碼如下&#xff1a; <!DOCTYPE html> <html> <head><style>/* 設置高度寬度100%并且左右居中、上下居中 */html,body {width: 100%;height: 100%;display: flex…

RENISHAW雷尼紹雙讀數頭系統應用分享

在精密回轉運動控制中&#xff0c;大多數場合都會對系統的回轉定位精度有嚴格的要求&#xff0c;RENISHAW雷尼紹圓光柵系統&#xff08;RESM增量和RESA絕對值&#xff09;對于回轉角度的反饋測量方案能有效的解決運動控制對回轉精度的需求。但是配置單個讀數頭的圓光柵系統的精…

C#最優隊列最小堆小頂堆大頂堆小根堆大根堆PriorityQueue的使用

最優隊列有多種叫法&#xff0c;什么小根堆&#xff0c;大根堆&#xff0c;小頂堆&#xff0c;大頂堆。 隊列分多種&#xff0c;線性隊列&#xff08;簡單隊列&#xff09;&#xff0c;循環隊列&#xff0c;最優隊列等等。 最優隊列&#xff0c;可以看作堆疊箱子&#xff0c;…