真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

JDK源碼分析(9)之WeakHashMap相關(guān)

平時(shí)我們使用最多的數(shù)據(jù)結(jié)構(gòu)肯定是 HashMap,但是在使用的時(shí)候我們必須知道每個(gè)鍵值對的生命周期,并且手動清除它;但是如果我們不是很清楚它的生命周期,這時(shí)候就比較麻煩;通常有這樣幾種處理方式:

創(chuàng)新互聯(lián)是一家專注于網(wǎng)站建設(shè)、成都網(wǎng)站建設(shè)與策劃設(shè)計(jì),延邊朝鮮族網(wǎng)站建設(shè)哪家好?創(chuàng)新互聯(lián)做網(wǎng)站,專注于網(wǎng)站建設(shè)10年,網(wǎng)設(shè)計(jì)領(lǐng)域的專業(yè)建站公司;建站業(yè)務(wù)涵蓋:延邊朝鮮族等地區(qū)。延邊朝鮮族做網(wǎng)站價(jià)格咨詢:028-86922220

  • 由一個(gè)線程定時(shí)處理,可以是Timer或者ScheduledThreadPoolExecutor;

  • 利用重寫LinkedHashMap.removeEldestEntry(),實(shí)現(xiàn) FIFOCache 或者 LRUCache;可以參考我之前寫的一篇文章?LinkedHashMap 相關(guān);

  • 利用?WeakHashMap?的特性,如果邏輯比較復(fù)雜還可以直接使用Reference;這里可以參考?Reference 完全解讀?和?Reference 框架概覽;

所以本文將主要介紹WeakHashMap的特性,以及補(bǔ)充一些關(guān)于 HashMap 實(shí)現(xiàn)的對比;相關(guān) HashMap 的介紹也可以參考?HashMap 相關(guān);

一、使用場景

上面也介紹了,WeakHashMap適用于不是非常重要的緩存類似的場景;例如:

WeakHashMap?map?=?new?WeakHashMap<>();for?(int?i?=?0;?i?

// 打?。?br />100
100
100
46
{}
0

對于以上的結(jié)果你可能和我打印的不一樣,WeakHashMap按照語義應(yīng)該是,當(dāng) key 沒有強(qiáng)引用指向的時(shí)候,會自動清除 key 和 value;我這里先解釋它的釋放過程,如果你覺得很清晰,那WeakHashMap你就算是掌握了;

  • 首先 for 循環(huán)結(jié)束的時(shí)候,key 已經(jīng)沒用強(qiáng)引用指向了,此時(shí)所有的 key 都是弱引用了;

  • 接下來執(zhí)行1,因?yàn)槲疫@里只有一個(gè)方法,新生代還有足夠的空間,所以不會觸發(fā) GC,所以所有的 key 任然在堆里面,所以打印100;

  • 然后手動觸發(fā) GC,雖然System.gc();不一定會立即執(zhí)行,但是我這里只有一個(gè)方法,所以肯定會執(zhí)行 GC,這里可以打開 GC 日志查看,-verbose:gc;因?yàn)?所有的 key 都是弱引用,所以referent被致為 null,同時(shí)將 key 注冊到?ReferenceQueue中;

  • 在執(zhí)行 3-7 的時(shí)候,按語義 map 應(yīng)該為空;但是將 key 注冊到?ReferenceQueue并非原子性一次完成的,所以這里會打印不同的值,每注冊完成一個(gè),在 map 進(jìn)行操作的時(shí)候,就會將其移除;

將上面的代碼改成多線程分析思路也是一樣的,如果你覺得有不清楚的地方可以查看下文;

二、WeakHashMap 源碼分析

1. 類定義

public?class?WeakHashMap?extends?AbstractMap?implements?Map

可以看到雖然WeakHashMap也是基于哈希表,但是卻并非像LinkedHashMap一樣是繼承于HashMap,并且WeakHashMap也沒有實(shí)現(xiàn)Cloneable, Serializable兩個(gè)接口,這是因?yàn)?code>WeakHashMap基于WeakReference實(shí)現(xiàn)的,弱引用并不建議實(shí)現(xiàn)序列化,同時(shí)弱引用一般用于不是很重要的緩存,也就沒必要實(shí)現(xiàn)Cloneable, Serializable兩個(gè)接口了;

2. 核心方法

private?final?ReferenceQueue?queue?=?new?ReferenceQueue<>();private?static?class?Entry?extends?WeakReference?implements?Map.Entry?{
??V?value;??final?int?hash;
??Entry?next;

??Entry(Object?key,?V?value,?ReferenceQueue?queue,?int?hash,?Entry?next)?{????super(key,?queue);????this.value?=?value;????this.hash??=?hash;????this.next??=?next;
??}??public?K?getKey()?{?}??public?V?getValue()?{??public?V?setValue(V?newValue)?{??public?int?hashCode()?{??public?String?toString()?{
}private?void?expungeStaleEntries()?{??for?(Object?x;?(x?=?queue.poll())?!=?null;?)?{????synchronized?(queue)?{??????@SuppressWarnings("unchecked")
????????Entry?e?=?(Entry)?x;??????int?i?=?indexFor(e.hash,?table.length);

??????Entry?prev?=?table[i];
??????Entry?p?=?prev;??????while?(p?!=?null)?{
????????Entry?next?=?p.next;????????if?(p?==?e)?{??????????if?(prev?==?e)
????????????table[i]?=?next;??????????else
????????????prev.next?=?next;??????????//?Must?not?null?out?e.next;
??????????//?stale?entries?may?be?in?use?by?a?HashIterator
??????????e.value?=?null;?//?Help?GC
??????????size--;??????????break;
????????}
????????prev?=?p;
????????p?=?next;
??????}
????}
??}
}

上面代碼所列的ReferenceQueue,Entry,expungeStaleEntries()就是WeakHashMap實(shí)現(xiàn)的核心了;這里強(qiáng)烈建議要先看?Reference 完全解讀?和?Reference 框架概覽這兩篇文章,里面同樣的內(nèi)容我也不會再贅述了;