1. 程式人生 > >WeakHashMap 源碼理解

WeakHashMap 源碼理解

概念 存在 ash kref dex 清空 adl pre nbsp

WeakHashMap,從名字可以看出它是某種 Map。它的特殊之處在於 WeakHashMap 裏的entry可能會被GC自動刪除,即使程序員沒有調用remove()或者clear()方法。

WeekHashMap 的這個特點特別適用於需要緩存的場景。在緩存場景下,由於內存是有限的,不能緩存所有對象;對象緩存命中可以提高系統效率。

要明白 WeekHashMap 的工作原理,還需要引入一個概念:弱引用(WeakReference)。我們都知道Java中內存是通過GC自動管理的,GC會在程序運行過程中自動判斷哪些對象是可以被回收的,並在合適的時機進行內存釋放。GC判斷某個對象是否可被回收的依據是,是否有有效的引用指向該對象

。如果沒有有效引用指向該對象(基本意味著不存在訪問該對象的方式),那麽該對象就是可回收的。這裏的“有效引用”並不包括弱引用。也就是說,雖然弱引用可以用來訪問對象,但進行垃圾回收時弱引用並不會被考慮在內,僅有弱引用指向的對象仍然會被GC回收

WeakHashMap 內部是通過弱引用來管理entry的,弱引用的特性對應到 WeakHashMap 上意味著什麽呢?將一對key, value放入到 WeakHashMap 裏並不能避免該key值被GC回收,除非在 WeakHashMap 之外還有對該key的強引用

重點:自帶清理功能的Map。

 // 清空table中無用鍵值對。原理如下:
 // (01) 當WeakHashMap中某個“弱引用的key”由於沒有再被引用而被GC收回時,
 //   被回收的“該弱引用key”也被會被添加到"ReferenceQueue(queue)"中。
 // (02) 當我們執行expungeStaleEntries時,
 //   就遍歷"ReferenceQueue(queue)"中的所有key     
// 然後就在“WeakReference的table”中刪除與“ReferenceQueue(queue)中key”對應的鍵值對
/**
     * Expunges stale entries from the table.
     */
    private void expungeStaleEntries() {
    Entry<K,V> e;
        while ( (e = (Entry<K,V>) queue.poll()) != null) {
            int h = e.hash;
            int i = indexFor(h, 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) { if (prev == e) table[i] = next; else prev.next = next; e.next = null; // Help GC e.value = null; // " " size--; break; } prev = p; p = next; } } }

我竟然以為weakhashMap 用 線性試探法解決的hash沖突。哈哈。ThreadLocalMap 用這貨解決的hash沖突,記混了!!

WeakHashMap 源碼理解