使用弱引用是我从未见过的实现,所以我试图弄清楚它们的用例是什么以及实现如何工作。您何时需要使用WeakHashMap
或WeakReference
以及如何使用?
答案 0 :(得分:94)
强引用的一个问题是 缓存,特别是非常大 像图像的结构。假设你 有一个必须工作的应用程序 用户提供的图像,如 我工作的网站设计工具。 当然你想要缓存这些 图像,因为从磁盘加载它们 是非常昂贵的,你想 避免有两个人的可能性 副本(可能是巨大的) 图像在内存中一次。
因为应该使用图像缓存 阻止我们重新加载图像时 我们并非绝对需要,你会的 快速意识到缓存应该 始终包含对any的引用 已经在记忆中的图像。同 但是,普通的强引用, 该引用本身将迫使 图像留在内存中,哪个 要求你以某种方式确定何时 不再需要图像了 内存并将其从缓存中删除, 这样它才有资格获得 垃圾收集。你被迫 复制垃圾的行为 收集器并手动确定 一个物体是否应该进入 存储器中。
Understanding Weak References,Ethan Nicholas
答案 1 :(得分:52)
要明确的一个区别是WeakReference
和SoftReference
之间的区别。
一旦引用的对象没有 hard 引用它,基本上JVM会急切地WeakReference
为GC-d。另一方面,SoftReference
d对象往往会被垃圾收集器留下,直到真正需要回收内存为止。
值保存在WeakReference
内的缓存非常无用(在WeakHashMap
中,它是弱引用的键)。当你想要实现一个可以用可用内存增长和缩小的缓存时,SoftReferences
对于包装值非常有用
答案 2 :(得分:29)
WeakReference
和WeakHashMap
的一个常见用途是用于向对象添加属性。有时您希望向对象添加一些功能或数据,但子类和/或组合不是一个选项,在这种情况下,显而易见的事情是创建一个hashmap,将您想要扩展的对象链接到要添加的属性。然后,无论何时您需要房产,您都可以在地图上查找。但是,如果要添加属性的对象往往会被破坏并被大量创建,那么地图中的许多旧对象最终会占用大量内存。
如果您使用WeakHashMap
代替对象将在您的地图不再被其他程序使用时离开地图,这是理想的行为。
我必须这样做才能将一些数据添加到java.awt.Component
以解决JRE在1.4.2和1.5之间的变化,我可以通过继承我感兴趣的每个组件来修复它({{1 }},JButton
,JFrame
....)但是使用更少的代码会更容易。
答案 3 :(得分:19)
WeakHashMap
和WeakReference
的另一个有用案例是侦听器注册表实现。
当您创建想要收听某些事件的内容时,通常会注册一个听众,例如
manager.registerListener(myListenerImpl);
如果manager
将您的听众存储为WeakReference
,则表示您无需删除该注册表,例如使用manager.removeListener(myListenerImpl)
,因为一旦您的侦听器或包含侦听器的组件变得不可用,它将自动删除。
当然你仍然可以手动删除你的监听器,但如果你没有,或者你忘了它,它不会导致内存泄漏,并且它不会阻止你的监听器被垃圾收集。
WeakHashMap
在哪里出现?
用于存储已注册侦听器的侦听器注册表WeakReference
需要一个集合来存储这些引用。标准Java库中只有WeakHashSet
实现只有WeakHashMap
,但我们可以轻松地使用后者来“实现”第一个的功能:
Set<ListenerType> listenerSet =
Collections.newSetFromMap(new WeakHashMap<ListenerType, Boolean>());
使用此listenerSet
注册新的侦听器,您只需将其添加到集合中,即使未显式删除它,如果不再引用侦听器,它也将由JVM自动删除
答案 4 :(得分:4)
此博客文章演示了两个类的使用:Java: synchronizing on an ID。用法如下:
private static IdMutexProvider MUTEX_PROVIDER = new IdMutexProvider();
public void performTask(String resourceId) {
IdMutexProvider.Mutex mutext = MUTEX_PROVIDER.getMutex(resourceId);
synchronized (mutext) {
// look up the resource and do something with it
}
}
IdMutextProvider提供基于id的对象进行同步。要求是:
这是使用类型为
的内部存储地图实现的WeakHashMap<Mutex, WeakReference<Mutex>>
对象既是键又是值。如果地图外部没有任何对该对象的硬引用,则可以对其进行垃圾回收。映射中的值与硬引用一起存储,因此必须将值包装在 WeakReference 中以防止内存泄漏。最后一点包含在javadoc。
中答案 5 :(得分:3)
例如,如果您想跟踪某个类创建的所有对象。要仍然允许对这些对象进行垃圾回收,您需要保留对象的弱引用列表/映射,而不是对象本身。
现在如果有人可以向我解释虚构参考,我会很高兴......
答案 6 :(得分:3)
如上所述,只要存在强引用,就会保留弱引用。
一个示例用法是在侦听器中使用WeakReference,以便一旦对其目标对象的主要引用消失,侦听器就不再处于活动状态。 请注意,这并不意味着从侦听器列表中删除了WeakReference,仍然需要清理,但可以执行清理,例如,在预定时间执行清理。 这还具有防止被监听对象持有强引用并最终成为内存膨胀的来源的效果。 示例:Swing GUI组件引用生命周期比窗口长的模型。
在如上所述与听众一起玩的同时,我们很快意识到,从用户的角度“立即”收集对象。
答案 7 :(得分:2)
我对WeakReferences的一个真实世界用途是,如果你有一个很少使用的单个非常大的对象。你不想在不需要的时候将它保存在内存中;但是,如果另一个线程需要相同的对象,你也不希望它们中的两个在内存中。您可以在某处保留对该对象的弱引用,以及使用它的方法中的硬引用;当方法都完成时,将收集对象。
答案 8 :(得分:1)
我做了一个谷歌代码搜索“new WeakHashMap()”。
我从GNU类路径项目和
获得了一堆匹配答案 9 :(得分:-1)
您可以使用weakhashmap为扩展对象创建实现无资源缓存。
但请注意,不希望有可变对象。 我使用它来缓存查询结果(大约需要400毫秒才能执行)到文本搜索引擎,这很少更新。