WeakHashMap原理分析

WeakHashMap总体介绍

​ WeakHashMap继承自AbstractMap,实现了Map接口,拥有了Map的基础功能。但是与常用的Map(比如HashMap)不同的是,WeakHashMap底层的存储单元Entry采用WeakReference,在GC的时候,会回收K,V。所以WeakHashMap天然比较适合用作缓存,即使K,V丢失,也不会对业务造成影响。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
private static class Entry<K,V> extends WeakReference<Object> implements Map.Entry<K,V> {
V value;
final int hash;
Entry<K,V> next;

/**
* Creates new entry.
*/
Entry(Object key, V value,
ReferenceQueue<Object> queue,
int hash, Entry<K,V> next) {
super(key, queue);
this.value = value;
this.hash = hash;
this.next = next;
}

...
}

​ 如上代码可以看到Entry继承了WeakReference,在构造函数中super(key, queue)传入了key和ReferenceQueue。

​ 在调用get(),put(),size()等方法的时候,会执行一个私有方法expungeStaleEntries,如下所示。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
private void expungeStaleEntries() {
//迭代弱引用队列中要被回收的对象
for (Object x; (x = queue.poll()) != null; ) {
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) {
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,map的value会泄漏。
e.value = null; // Help GC
size--;
break;
}
prev = p;
p = next;
}
}
}
}

#图解WeakHashMap原理

img

​ 图1

​ 如图1所示,key1,key2,key3虚引用指向Entry1,Entry2,Entry3,每个entry又分别指向v1,v2,v3。GC之后,key2虚引用被垃圾回收。通过执行expungeStaleEntries方法,使得Entry2变成游离态,Entry2也和v2脱离了引用关系。所以Entry2,v2都变成了可被垃圾回收的状态。

img

​ 图2

# java

评论