我从未见过对弱引用的实现,因此正在尝试弄清楚它们的用例以及如何实现。您何时需要使用WeakHashMap
或WeakReference
,并且它是如何被使用的?
我从未见过对弱引用的实现,因此正在尝试弄清楚它们的用例以及如何实现。您何时需要使用WeakHashMap
或WeakReference
,并且它是如何被使用的?
因为图像缓存应该防止我们在不绝对需要时重新加载图像,所以您很快就会意识到缓存始终应该包含对任何已经在内存中的图像的引用。然而,使用普通的强引用,该引用本身将强制图像保留在内存中,这要求您某种方式确定何时不再需要内存中的图像并将其从缓存中删除,以便它变得可以进行垃圾回收。您被迫重复垃圾收集器的行为并手动确定对象是否应该在内存中。
理解弱引用, Ethan Nicholas
WeakHashMap
管理操作系统资源。 - Jacob KrallWeakReference
与SoftReference
需要明确的是,WeakReference
和SoftReference
之间的区别。
基本上,一旦引用对象没有硬引用,WeakReference
将被JVM迅速地GC-d。另一方面,SoftReference
对象通常会被垃圾回收器保留,直到它真正需要回收内存。
如果在缓存中使用WeakReference
来保存值,那么这将是相当无用的(在WeakHashMap
中,是键被弱引用)。当你想要实现一个可以随着可用内存而增长和缩小的缓存时,可以使用SoftReferences
来包装值。
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也会自动删除它。
WeakHashMap
有用的情况是每当你需要一个对象的HashMap
时。所以哇,你永远不必手动执行hashmap.remove,因为一旦对象超出范围,项目就会自动删除!真是魔法!这样一个丑陋的魔法黑客是一个完全的脸掌。 - Pacerierprivate 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中有详细说明。
现在如果有人能向我解释虚引用,我会很高兴...
我在实际应用中使用弱引用的一个例子是,当你有一个很大的对象,但它很少被使用时。你不想在不需要它时将其保留在内存中;但是,如果另一个线程需要相同的对象,你也不希望在内存中有两个对象。你可以在某个地方保持对该对象的弱引用,并在使用它的方法中保留对该对象的硬引用;当这些方法都完成时,该对象将被收集。
你可以使用WeakHashMap来实现资源免费的缓存,用于大量对象的创建。
但请注意,不要使用可变对象。 我将其用于缓存查询结果(大约需要400毫秒执行)到文本搜索引擎中,这个搜索引擎很少更新。