Java的WeakHashMap和缓存:为什么它引用键而不是值?

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (2)
  • 关注 (0)
  • 查看 (21)

Java的WeakHashMap通常被认为对缓存很有用。看起来很奇怪,它的弱引用是根据地图的键而定义的,而不是它的值。我的意思是,这是我想要缓存的值,并且我想要一次性收集垃圾,除了缓存之外没有其他人强烈引用它们,不是吗?

以哪种方式帮助保持键的弱引用?如果你做了一个ExpensiveObject o = weakHashMap.get("some_key"),那么我希望缓存保持为'o',直到调用者不再拥有强引用,并且我完全不关心字符串对象“some_key”。

我错过了什么吗?

提问于
用户回答回答于

WeakHashMap 作为缓存没有用处,至少大多数人认为它有用的。正如你所说,它使用弱,而不是弱,所以它不是为大多数人想要使用它而设计的(事实上,我看到有人用它来错误地)。

WeakHashMap主要用于保存关于您不控制生命周期的对象的元数据。例如,如果您有一堆对象在您的课程中传递,并且您希望跟踪有关它们的额外数据,而不需要在超出范围时收到通知,并且不需要引用它们就可以保持活动状态。

一个简单的例子(和我以前用过的)可能是这样的:

WeakHashMap<Thread, SomeMetaData>

在那里你可以跟踪你的系统中的各种线程在做什么; 当线程死亡时,该条目将从您的映射中静默移除,并且如果您是最后一个引用,则不会阻止线程被垃圾收集。然后,您可以遍历该映射中的条目,以找出有关系统中活动线程的元数据。

对于您所使用的缓存类型,请使用专用缓存系统或查看Google收藏夹的MapMaker类 ; 就像是

new MapMaker().weakValues().makeMap();

会做你以后的事情,或者如果你想变得有趣,你可以添加超时到期:

new MapMaker().weakValues().expiration(5, TimeUnit.MINUTES).makeMap();
用户回答回答于

主要用途WeakHashMap是当你的映射消失时你想消失的映射。缓存是相反的 - 你有映射,当它们的值消失时你想消失。

对于缓存,你想要的是一个Map<K,SoftReference<V>>SoftReference当内存变得紧张时,A 将被垃圾收集。(将其与a相对比WeakReference,只要不再对其指示对象进行硬引用,就可以将其清除)。您希望引用在缓存中很软(至少在键值映射不会过时的情况下) ),因为如果稍后再查找它们,您的值仍有可能仍在缓存中。如果引用很弱,那么您的值将立即被刷新,从而破坏缓存的目的。

为了方便起见,您可能希望隐藏实现中的SoftReferenceMap,以便缓存看起来类型<K,V>而不是<K,SoftReference<V>>。如果你想这样做,这个问题有网络上提供的实现的建议。

还要注意,当你SoftReference在a中使用值时Map,你必须做一些操作来删除已经SoftReferences被清除的键值对,否则你的Map内存会泄漏。

扫码关注云+社区