一文带你了解WeakHashMap

1. WeakHashMap的适用场景

大部分的缓存都需要占用内存,考虑到内存的有限性,并不能缓存所有的对象,此时就需要用到另类的集合,例如WeakHashMap,可以保存一些对象的同时淘汰另一些对象,以此减少存储成本。

2. 什么是WeakHashMap

WeakHashMap,是在HashMap的基础上多了Weak。表示这是一个弱引用的HashMap。

来看下WeakHashMap的类定义:

public class WeakHashMap<K,V>
    extends AbstractMap<K,V>
    implements Map<K,V> {

那WeakHashMap和HashMap有什么区别呢?

3. WeakHashMap和HashMap的区别

在比较WeakHashMap和HashMap的区别之前,先来讲一下弱引用(WeakReference)

关于弱引用

Java有4种引用,强引用(Strong),弱引用(Weak),软引用(soft),虚引用(phantom)。

弱引用表示一个非必需的对象,强度低于软引用,需要通过WeakReference类来间接引用目标对象。被弱引用关联的对象只能存活到下一次垃圾回收发生之前,当触发垃圾回收时,无论当前内存是否足够,都会回收掉只被弱引用关联的对象

注意:如果这个对象还被强引用所引用,那么就不会被回收

简单了解了弱引用之后,我们做一个
总结:
区别于HashMap的强键,WeakHashMap是弱键。
弱键的作用是随时可能被垃圾回收器回收。

4. WeakHashMap的实现原理

主要通过WeakReference和ReferenceQueue实现

来看下源码:

    /**
     * The entries in this hash table extend WeakReference, using its main ref
     * field as the key.
     */
    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;
        }

        @SuppressWarnings("unchecked")
        public K getKey() {
            return (K) WeakHashMap.unmaskNull(get());
        }

        public V getValue() {
            return value;
        }

        public V setValue(V newValue) {
            V oldValue = value;
            value = newValue;
            return oldValue;
        }
  1. 新建WeakHashMap,将Entry添加到WeakHashMap中,通过数组table保存Entry。
  2. 弱键在没有被强引用引用的前提下,下一次GC将回收该弱键并添加到ReferenceQueue(queue)队列中。
  3. 再一次操作WeakHashMap时,会先同步table和queue。table中保存了全部的entry,queue中保存被GC回收的entry;同步它们,就是删除table中被GC回收的键值对。
 /**
     * Expunges stale entries from the table.
     */
    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; // Help GC
                        size--;
                        break;
                    }
                    prev = p;
                    p = next;
                }
            }
        }
    }

WeakHashMap中的大部分操作都会调用expungeStaleEntries()这个方法,储存被gc回收对象的queue会接收gc发送的回收消息,将queue中的key所对应的value赋值null,帮助完成对Entry的回收工作。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值