緩存 -- LRU算法

什么是LRU算法

????LRU算法的全稱Least Recently Used孝鹊。即最近最少使用。
????LRU算法是內(nèi)存管理的一種頁面置換算法,對于在內(nèi)存中但是又不用的數(shù)據(jù)塊叫做LRU挺狰,操作系統(tǒng)會將那些數(shù)據(jù)數(shù)據(jù)LRU而將其移除內(nèi)存騰出空間來加載其他數(shù)據(jù)(以上來自百度百科)。


LRU算法的實現(xiàn)

????LRU算法通常是基于雙向鏈表來實現(xiàn)的壮不,下面我們一起看一下雙向鏈表是如何實現(xiàn)LRU算法的蔼夜。


image.png

????如上圖所示判呕,我們定義了一個雙向鏈表尘喝。對鏈表中元素的操作不外乎四種:get磁浇,put,remove朽褪,update置吓。其中remove操作,刪除鏈表中的一個元素缔赠,不會影響鏈表中現(xiàn)有的排序情況衍锚,而update和put操作可以看作是同一種操作。所以我們主要看get嗤堰,put操作對鏈表中元素的影響戴质。


image.png

image.png

????以上我們看到當在雙向鏈表中發(fā)生get和put操作時,鏈表內(nèi)元素的變化情況踢匣。下面再來看一下基于LinkedHashMap的LRU算法是如何實現(xiàn)的置森。

基于LinkedHashMap的LRU算法實現(xiàn)

????LinkedHashMap中LRU算法的實現(xiàn)主要依賴的幾個方法。

  1. afterNodeInsertion(boolean evict)
    void afterNodeInsertion(boolean evict) { // possibly remove eldest
        LinkedHashMap.Entry<K,V> first;
        // first = head 這一步是關鍵符糊,從if的判斷條件中可以看出,在鏈表的頭結點head存在的情況下呛凶,會將head賦值給first男娄,然后交給removeEldestEntry(first)執(zhí)行
        if (evict && (first = head) != null && removeEldestEntry(first)) {
            K key = first.key;
            // 該方法移除的是鏈表的頭結點
            removeNode(hash(key), key, null, false, true);
        }
    }

  1. afterNodeAccess(Node<K,V> e)
    void afterNodeAccess(Node<K,V> e) { // move node to last
        LinkedHashMap.Entry<K,V> last;
        // 執(zhí)行移動操作的前提是accessOrder和要移動的元素e != tail,這是為什么呢漾稀,剛開始看到這樣的代碼我也疑惑模闲,說好的移動到鏈表的頭部呢?撓頭
        if (accessOrder && (last = tail) != e) {
        // 下面的代碼就是我們熟知的雙向鏈表中元素的移動操作了崭捍。
            LinkedHashMap.Entry<K,V> p =
                (LinkedHashMap.Entry<K,V>)e, b = p.before, a = p.after;
            p.after = null;
            if (b == null)
                head = a;
            else
                b.after = a;
            if (a != null)
                a.before = b;
            else
                last = b;
            if (last == null)
                head = p;
            else {
                p.before = last;
                last.after = p;
            }
            tail = p;
            ++modCount;
        }
    }

  1. removeEldestEntry(Map.Entry<K,V> eldest)
protected boolean removeEldestEntry(Map.Entry<K,V> eldest) {
   // 默認返回false尸折,也就是不移除最老的元素,我們需要重新改寫該方法殷蛇,在當前容量大于預設的最大容量時实夹,移除最老元素。 
   return false;
}

????介紹完幾個關鍵方法之后粒梦,我們來從整體的角度看一下這幾個方法在整個流程中的作用亮航。


image.png

image.png

Demo

public class LruCache {

    private Map<Object, Object> cache;

    LruCache(int size) {
        // 初始化LinkedHashMap三個參數(shù),容量匀们,負載引子缴淋,accessOrder
        this.cache = new LinkedHashMap<Object, Object>(size, 0.75f, true) {
            @Override
            protected boolean removeEldestEntry(Map.Entry<Object, Object> eldest) {
               // 比較當前LinkedHashMap中的節(jié)點數(shù)量與允許存放最大數(shù)量的比較
                return super.size() > size;
            }
        };
    }

    public Object put(Object key, Object value) {
        return cache.put(key, value);
    }

    public Object get(Object key) {
        return cache.get(key);
    }
}
最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子重抖,更是在濱河造成了極大的恐慌露氮,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,607評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件钟沛,死亡現(xiàn)場離奇詭異畔规,居然都是意外死亡,警方通過查閱死者的電腦和手機讹剔,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,239評論 3 395
  • 文/潘曉璐 我一進店門油讯,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人延欠,你說我怎么就攤上這事陌兑。” “怎么了由捎?”我有些...
    開封第一講書人閱讀 164,960評論 0 355
  • 文/不壞的土叔 我叫張陵兔综,是天一觀的道長。 經(jīng)常有香客問我狞玛,道長软驰,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,750評論 1 294
  • 正文 為了忘掉前任心肪,我火速辦了婚禮锭亏,結果婚禮上,老公的妹妹穿的比我還像新娘硬鞍。我一直安慰自己慧瘤,他們只是感情好,可當我...
    茶點故事閱讀 67,764評論 6 392
  • 文/花漫 我一把揭開白布固该。 她就那樣靜靜地躺著锅减,像睡著了一般。 火紅的嫁衣襯著肌膚如雪伐坏。 梳的紋絲不亂的頭發(fā)上怔匣,一...
    開封第一講書人閱讀 51,604評論 1 305
  • 那天,我揣著相機與錄音桦沉,去河邊找鬼每瞒。 笑死,一個胖子當著我的面吹牛纯露,可吹牛的內(nèi)容都是我干的独泞。 我是一名探鬼主播,決...
    沈念sama閱讀 40,347評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼苔埋,長吁一口氣:“原來是場噩夢啊……” “哼懦砂!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 39,253評論 0 276
  • 序言:老撾萬榮一對情侶失蹤荞膘,失蹤者是張志新(化名)和其女友劉穎罚随,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體羽资,經(jīng)...
    沈念sama閱讀 45,702評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡淘菩,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,893評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了屠升。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片潮改。...
    茶點故事閱讀 40,015評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖腹暖,靈堂內(nèi)的尸體忽然破棺而出汇在,到底是詐尸還是另有隱情,我是刑警寧澤脏答,帶...
    沈念sama閱讀 35,734評論 5 346
  • 正文 年R本政府宣布糕殉,位于F島的核電站,受9級特大地震影響殖告,放射性物質(zhì)發(fā)生泄漏阿蝶。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,352評論 3 330
  • 文/蒙蒙 一黄绩、第九天 我趴在偏房一處隱蔽的房頂上張望羡洁。 院中可真熱鬧,春花似錦爽丹、人聲如沸筑煮。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,934評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至嚼隘,卻和暖如春诽里,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背飞蛹。 一陣腳步聲響...
    開封第一講書人閱讀 33,052評論 1 270
  • 我被黑心中介騙來泰國打工谤狡, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人卧檐。 一個月前我還...
    沈念sama閱讀 48,216評論 3 371
  • 正文 我出身青樓墓懂,卻偏偏與公主長得像,于是被迫代替她去往敵國和親霉囚。 傳聞我的和親對象是個殘疾皇子捕仔,可洞房花燭夜當晚...
    茶點故事閱讀 44,969評論 2 355

推薦閱讀更多精彩內(nèi)容