关于SoftHashMap实现相关内容

前言

在看这篇文章时,看到了里面使用了SoftHashMap类。这个类是Shiro框架中的一个类,博主把这个类拿过来后,又添加了一个新的方法来方便使用。

在看到这个类后,考虑了个问题:

  • 会不会发生GC后,SoftHashMap里的Value被回收了,而Key还存在的问题呢?(如果会发生这样的问题的话,我们就无法用Key来判断缓存是否存在了。)

下面我们看一下它是如何处理的。

正文

1,会不会发生GC后,SoftHashMap里的Value被回收了,而Key还存在的问题呢?

答案是:会。
为什么会发生这种事呢?我们先看看源码:

/**
 * We define our own subclass of SoftReference which contains
 * not only the value but also the key to make it easier to find
 * the entry in the HashMap after it's been garbage collected.
 */
private static class SoftValue<V, K> extends SoftReference<V> {

    private final K key;

    /**
     * Constructs a new instance, wrapping the value, key, and queue, as
     * required by the superclass.
     *
     * @param value the map value
     * @param key   the map key
     * @param queue the soft reference queue to poll to determine if the entry had been reaped by the GC.
     */
    private SoftValue(V value, K key, ReferenceQueue<? super V> queue) {
        super(value, queue);
        this.key = key;
    }

}

在上面的源码是一个类定义,保存SoftHashMap中的实例,就是上面的SoftValue类型。
这个SoftValue是如何实现的呢?主要是两点:

  • 继承了SoftReference<V>
  • 声明一个内部变量key,作为Map中的Key

仔细看一下内部代码,“V”所代表的Value被保存到了SoftReference中,而Key则没有。也就是说,当GC自动回收时,“V”所代表的Value会被回收走,但Key不会。


2,SoftHashMap是如何解决Key不自动清除的问题的呢?

在SoftHashMap类中,有一个方法叫做processQueue,代码如下:

private void processQueue() {
    SoftValue sv;
    while ((sv = (SoftValue) queue.poll()) != null) {
        //noinspection SuspiciousMethodCalls
        map.remove(sv.key); // we can access private data!
    }
}

这个方法的作用是,从定义的queue里取得“被回收的SoftValue”,然后通过SoftValue的Key,把被回收的SoftValue从Map里删除掉。(虽然SoftValue被收回了,但SoftValue的Key在Map里还有一个强引用,所以Key没有被回收。)
看一下processQueue被调用的地方,在get、put、containsValue等方法的第一行语句,都调用这个“从Map里清除失效缓存”的方法。也就是说,在执行操作之前,先清除一下失效的缓存,这样就不会出现“Key还在,但Value被清除掉的”情况了。

3,为什么被GC清除掉的缓存会保存到ReferenceQueue里呢?

首先我们先看看ReferenceQueue的作用是什么。

如果构造在“弱/软引用”实例时,把ReferenceQueue当做构造函数参数传给实例的话,在“弱/软引用”被GC清除时,会把被清除的实例的引用放到ReferenceQueue里。

所以ReferenceQueue就是用来装被清除的“弱/软引用”的实例的。


在SoftValue的构造函数中,会使用SoftHashMap中声明的ReferenceQueue来构造SoftValue的实例。代码如下:

private SoftValue(V value, K key, ReferenceQueue<? super V> queue) {
    super(value, queue);
    this.key = key;
}

通过上面的说明,我们明白了这个SoftHashMap类,是如何解决Key遗留的问题了。


参考:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值