weakHashMap解析
weakHashMap
包路徑:package java.util;
import java.lang.ref.WeakReference;
import java.lang.ref.ReferenceQueue;
public class WeakHashMap<K,V> extends AbstractMap<K,V> implements Map<K,V>
1、繼承於AbstractMap,實現了Map介面。
2、weakHashMap是雜湊表,但是它的鍵是“弱鍵”,weakHashMap中保護幾個重要的成員變數:
table是一個Entry[ ]型別的陣列,而Entry是一個單向連結串列,雜湊表中的鍵值對都是儲存在Entry陣列中的。
size是表示儲存的鍵值對的數量大小。
threshold是閾值,用於判斷是否需要擴充容量。
loadFactor是載入因子。
modCount是用來實現fail-fast機制的。
queue儲存的是“已被GC清除的”“弱引用的鍵”。
3、該集合類的主要特點是:
隨著時間的推移,鍵值對會逐漸的減少----->GC 垃圾回收
基本原理:weakHashMap的特點是:當除了自身有對key的引用之外,此key沒有其他的引用,那麼weakHashMap會在下一次對weakHashMap進行增刪改查操作的時候及時丟棄該鍵值對,節約記憶體的使用,此特性使得weakHashMap比較適合構建快取系統。
weakHashMap主要是通過expungeStaleEntries函式來實現移除內部不用的Entry從而達到自動釋放內部的目的。
private void expungeStaleEntries() { for (Object x; (x = queue.poll()) != null; ) { 通過迴圈一直從queue中取出過期的entry,直至取完為止 synchronized (queue) { 通過加鎖進行刪除操作 @SuppressWarnings("unchecked") Entry<K,V> e = (Entry<K,V>) x; int i = indexFor(e.hash, table.length); Entry<K,V> prev = table[i]; Entry<K,V> p = prev; while (p != null) { Entry<K,V> next = p.next; if (p == e) { 在同步程式碼塊中先把queue中取出的Object型別的資料強制轉化為Entry物件e,然後計算此entry在桶中的位置,然後開始遍歷entry連結串列,如果此entry是連結串列頭,設定此entry的後繼為新的連結串列頭 if (prev == e) table[i] = next; else 然後將此entry的前序節點的後繼指標指向此entry的後繼節點 prev.next = next; 設定被刪除的entry的value為null,加速垃圾回收,相應的size-- e.value = null; // Help GC size--; break; } prev = p; p = next; }
4、弱鍵的原理------>大致是通過WeakReference和ReferenceQueue來實現的。
實現步驟:(1)建立weakHashMap的時候,將鍵值對存放到陣列連結串列當中;(2)當發生GC時會判斷key是否有物件引用,如果沒有引用了,就回收該key,意味著我們的entry實體從我們的集合中回收,回收的同時,將該物件加入到ReferenceQueue中;(3)在操作weakHashMap的時候,會首先同步table和Queue,table存放的是所有有效的鍵值對,Queue存放的是被回收的鍵值對,在table中刪除Queue中有的鍵值對。
5、關於Java中的4種引用
(WeakHashMap中使用WeakReference,也就是通過虛引用來實現的)
(1)強引用(Strong Reference)--->永遠不會回收被引用的物件,比如程式碼中new出來的物件
(2)軟引用(SoftReference)--->表示有用但是非必需的,如果系統記憶體資源緊張,可能就會被回收
(3)弱引用(WeakReference)--->表示非必需的物件,只能存活到下一次垃圾回收發生之前
(4)虛引用(PhantomReference)--->是最弱的,該引用無法操作物件
6、哪些方法會產生清理元素的操作?
put、get方法開始的getTable會呼叫一次expungeStaleEntries
resize方法開始的getTable會呼叫一次expungeStaleEntries
transfer方法本身會判斷弱引用指向的物件是否已經被GC
擴容之後發現size小於閾值的一半,會呼叫一次expungeStaleEntries
size方法會呼叫expungeStaleEntries