Java的WeakHashMap经常被认为对缓存很有用。虽然它的弱引用是根据map的键定义的,而不是它的值,但这似乎很奇怪。我的意思是,这是我想要缓存的值,当除了缓存之外没有其他人强烈引用它们时,我希望对它们进行垃圾回收,不是吗?
持有对键的弱引用在哪方面有帮助?如果你做一个ExpensiveObject o = weakHashMap.get("some_key")
,那么我希望缓存保持'o‘,直到调用者不再持有强引用,而我一点也不关心string对象"some_key“。
我是不是遗漏了什么?
发布于 2009-11-26 18:32:29
WeakHashMap作为缓存并不有用,至少在大多数人看来是这样。正如您所说,它使用弱键,而不是弱值,所以它不是为大多数人想要使用它的目的而设计的(事实上,我见过人们错误地使用它)。
WeakHashMap主要用于保存有关您不能控制其生命周期的对象的元数据。例如,如果有一堆对象在类中传递,并且希望跟踪有关这些对象的额外数据,而不需要在它们超出作用域时得到通知,并且不需要对它们的引用使它们保持活动状态。
一个简单的例子(也是我以前用过的例子)可能是这样的:
WeakHashMap<Thread, SomeMetaData>
在这里,您可以跟踪系统中的各个线程在做什么;当线程死亡时,条目将从映射中悄悄删除,并且如果您是对线程的最后一个引用,则不会阻止线程被垃圾回收。然后,您可以遍历该映射中的条目,以找出您拥有的有关系统中活动线程的元数据。
有关详细信息,请参阅WeakHashMap in not a cache!。
对于您想要的缓存类型,可以使用专用的缓存系统(例如EHCache),也可以查看Guava的MapMaker class;类似于
new MapMaker().weakValues().makeMap();
将会做你想做的事情,或者如果你想变得花哨,你可以添加timed expiration:
new MapMaker().weakValues().expiration(5, TimeUnit.MINUTES).makeMap();
发布于 2009-11-26 19:43:21
WeakHashMap
的主要用途是当您有希望在其键消失时消失的映射时。缓存正好相反-当映射的值消失时,您希望这些映射也消失。
对于缓存,您需要的是一个Map<K,SoftReference<V>>
。当内存变得紧张时,SoftReference
将被垃圾回收。(与此形成对比的是WeakReference
,一旦不再存在对其引用的硬引用,它可能会被清除。)您希望您的引用在缓存中是软的(至少在键-值映射不会过时的情况下是如此),因为如果您稍后查找这些值,则它们有可能仍然在缓存中。如果引用是弱的,那么您的值将立即被gc,这就违背了缓存的目的。
为方便起见,您可能希望将SoftReference
值隐藏在Map
实现中,以便您的缓存看起来是<K,V>
类型而不是<K,SoftReference<V>>
类型。如果你想这样做,this question在网上提供了一些关于实现的建议。
另请注意,当您在Map
中使用SoftReference
值时,您必须手动删除已清除其SoftReferences
的键值对-否则您的Map
将永远增大,并泄漏内存。
发布于 2011-06-21 03:35:56
另一件需要考虑的事情是,如果采用Map<K, WeakReference<V>>
方法,该值可能会消失,但映射不会消失。根据使用情况,您最终可能会得到一个Map,其中包含许多条目,这些条目的弱引用已被GC。
https://stackoverflow.com/questions/1802809
复制相似问题