Java 什么时候使用 WeakHashMap 或 WeakReference?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/154724/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
When would you use a WeakHashMap or a WeakReference?
提问by 18Rabbit
The use of weak references is something that I've never seen an implementation of so I'm trying to figure out what the use case for them is and how the implementation would work. When have you needed to use a WeakHashMap
or WeakReference
and how was it used?
弱引用的使用是我从未见过的实现,所以我试图弄清楚它们的用例是什么以及实现将如何工作。你什么时候需要使用WeakHashMap
orWeakReference
以及它是如何使用的?
采纳答案by Jacob Krall
One problem with strong references is caching, particular with very large structures like images. Suppose you have an application which has to work with user-supplied images, like the web site design tool I work on. Naturally you want to cache these images, because loading them from disk is very expensive and you want to avoid the possibility of having two copies of the (potentially gigantic) image in memory at once.
Because an image cache is supposed to prevent us from reloading images when we don't absolutely need to, you will quickly realize that the cache should always contain a reference to any image which is already in memory. With ordinary strong references, though, that reference itself will force the image to remain in memory, which requires you to somehow determine when the image is no longer needed in memory and remove it from the cache, so that it becomes eligible for garbage collection. You are forced to duplicate the behavior of the garbage collector and manually determine whether or not an object should be in memory.
强引用的一个问题是缓存,特别是对于像图像这样的非常大的结构。假设您有一个应用程序必须处理用户提供的图像,例如我使用的网站设计工具。自然地,您希望缓存这些图像,因为从磁盘加载它们非常昂贵,并且您希望避免在内存中同时拥有(可能是巨大的)图像的两个副本的可能性。
因为图像缓存应该防止我们在绝对不需要时重新加载图像,所以您很快就会意识到缓存应该始终包含对内存中已经存在的任何图像的引用。但是,对于普通的强引用,该引用本身将强制图像保留在内存中,这需要您以某种方式确定何时不再需要内存中的图像并将其从缓存中删除,以便它有资格进行垃圾回收。您被迫复制垃圾收集器的行为并手动确定对象是否应在内存中。
Understanding Weak References, Ethan Nicholas
理解弱引用,伊桑·尼古拉斯
回答by JesperE
If you for example want to keep track of all objects created of a certain class. To still allow these objects to be garbage collected, you keep a list/map of weak references to the objects instead of the objects themselves.
例如,如果您想跟踪某个类创建的所有对象。为了仍然允许这些对象被垃圾收集,您需要保留对对象的弱引用的列表/映射,而不是对象本身。
Now if someone could explain phantom-references to me, I'd be happy...
现在,如果有人可以向我解释幻象引用,我会很高兴......
回答by Jacob Krall
One real world use I had for WeakReferences is if you have a single, very large object that's rarely used. You don't want to keep it in memory when it's not needed; but, if another thread needs the same object, you don't want two of them in memory either. You can keep a weak reference to the object somewhere, and hard references in the methods that use it; when the methods both finish, the object will be collected.
我对 WeakReferences 的一个真实用途是,如果您有一个很少使用的非常大的对象。你不想在不需要的时候把它保存在内存中;但是,如果另一个线程需要同一个对象,那么您也不希望它们中的两个在内存中。您可以在某处保留对该对象的弱引用,并在使用它的方法中保留硬引用;当方法都完成时,对象将被收集。
回答by Andreas Petersson
you can use weakhashmap to implement a resource-free caching for expansive object creation.
您可以使用 weakhashmap 为扩展对象创建实现无资源缓存。
but note that it is not desireable to have mutable objects. i used it to cache query results (which take about 400 ms to execute) to a text-search engine, which is rarely updated.
但请注意,拥有可变对象是不可取的。我用它来将查询结果(执行大约需要 400 毫秒)缓存到很少更新的文本搜索引擎。
回答by anjanb
I did a google code search for "new WeakHashMap()".
我用谷歌代码搜索“new WeakHashMap()”。
I got a bunch of matches from the GNU classpath project and
我从 GNU 类路径项目中得到了一堆匹配项
- Apache xbean Project : WeakHashMapEditor.java
- Apache Lucene project : CachingWrapperFilter.java
- Apache xbean 项目:WeakHashMapEditor.java
- Apache Lucene 项目:CachingWrapperFilter.java
回答by McDowell
This blog post demonstrates the use of both classes: Java: synchronizing on an ID. The usage goes something like this:
这篇博文演示了这两个类的使用:Java:同步 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 provides id-based objects to synchronize on. The requirements are:
IdMutextProvider 提供基于 id 的对象进行同步。要求是:
- must return a reference to the same object for concurrent use of equivalent IDs
- must return a different object for different IDs
- no release mechanism (objects are not returned to the provider)
- must not leak (unused objects are eligible for garbage collection)
- 必须返回对同一对象的引用以同时使用等效 ID
- 必须为不同的 ID 返回不同的对象
- 没有释放机制(对象不会返回给提供者)
- 不得泄漏(未使用的对象有资格进行垃圾收集)
This is achieved using an internal storage map of type:
这是使用以下类型的内部存储映射来实现的:
WeakHashMap<Mutex, WeakReference<Mutex>>
The object is both key and value. When nothing external to the map has a hard reference to the object, it can be garbage collected. Values in the map are stored with hard references, so the value must be wrapped in a WeakReferenceto prevent a memory leak. This last point is covered in the javadoc.
对象既是键又是值。当地图外部的任何东西都没有对对象的硬引用时,它可以被垃圾收集。映射中的值使用硬引用存储,因此必须将该值包装在WeakReference 中以防止内存泄漏。最后一点在javadoc 中有介绍。
回答by oxbow_lakes
WeakReference
versus SoftReference
WeakReference
相对 SoftReference
One distinction to be clear on is the difference between a WeakReference
and a SoftReference
.
需要明确的一个区别是 aWeakReference
和 a之间的区别SoftReference
。
Basically a WeakReference
will be GC-dby the JVMeagerly, once the referenced object has no hardreferences to it. A SoftReference
d object on the other hand, will tend to be left about by the garbage collector until it really needs to reclaim the memory.
基本上,一旦被引用的对象没有对它的硬引用,JVM 就会急切地对aWeakReference
进行GC-d。另一方面,一个d 对象往往会被垃圾收集器留下,直到它真正需要回收内存。SoftReference
A cache where the valuesare held inside WeakReference
s would be pretty useless (in a WeakHashMap
, it is the keys which are weakly referenced). SoftReferences
are useful to wrap the values around when you want to implement a cache which can grow and shrink with the available memory.
将值保存在WeakReference
s 中的缓存将非常无用(在 a 中WeakHashMap
,弱引用的是键)。SoftReferences
当您想要实现可以随着可用内存增长和缩小的缓存时,将这些值包装起来很有用。
回答by Louis Jacomet
As stated above, weak reference are held for as long as a strong reference exists.
如上所述,只要存在强引用,就会保持弱引用。
An example usage would be to use WeakReference inside listeners, so that the listeners are no longer active once the main reference to their target object is gone. Note that this does not mean the WeakReference is removed from the listeners list, cleaning up is still required but can be performed, for example, at scheduled times. This has also the effect of preventing the object listened to from holding strong references and eventually be a source of memory bloat. Example: Swing GUI components refering a model having a longer lifecycle than the window.
一个示例用法是在侦听器中使用 WeakReference,这样一旦对目标对象的主要引用消失,侦听器就不再处于活动状态。请注意,这并不意味着 WeakReference 已从侦听器列表中删除,仍然需要清理,但可以执行,例如,在预定时间执行。这还具有防止所侦听的对象持有强引用并最终成为内存膨胀源的效果。示例:Swing GUI 组件引用了生命周期比窗口更长的模型。
While playing with listeners as described above we rapidly realised that objects get collected "immediately" from a user's point of view.
在与上述听众一起玩时,我们很快意识到从用户的角度来看,对象是“立即”收集的。
回答by luke
One Common use of WeakReference
s and WeakHashMap
s in particular is for adding properties to objects. Occasionally you want to add some functionality or data to an object but subclassing and/or composition are not an option in that case the obvious thing to do would be to create a hashmap linking the object you want to extend to the property you want to add. then whenever you need the property you can just look it up in the map. However, if the objects you are adding properties to tend to get destroyed and created a lot, you can end up with a lot of old objects in your map taking up a lot of memory.
WeakReference
s 和WeakHashMap
s 的一种常见用途是为对象添加属性。有时您想向对象添加一些功能或数据,但子类化和/或组合不是一种选择,在这种情况下,显而易见的事情是创建一个哈希图,将您想要扩展的对象链接到您想要添加的属性. 然后,无论何时您需要该物业,您都可以在地图上查找。但是,如果您要添加属性的对象往往会被销毁和创建很多,则最终可能会导致地图中的许多旧对象占用大量内存。
If you use a WeakHashMap
instead the objects will leave your map as soon as they are no longer used by the rest of your program, which is the desired behavior.
如果您使用 aWeakHashMap
代替,一旦程序的其余部分不再使用对象,它们就会离开您的地图,这是所需的行为。
I had to do this to add some data to java.awt.Component
to get around a change in the JRE between 1.4.2 and 1.5, I could have fixed it by subclassing every component I was interested int (JButton
, JFrame
, JPanel
....) but this was much easier with much less code.
我必须这样做来添加一些数据来java.awt.Component
解决 1.4.2 和 1.5 之间 JRE 中的更改,我可以通过对我感兴趣的每个组件进行子类化来修复它 int ( JButton
, JFrame
, JPanel
....) 但这是很多用更少的代码更容易。
回答by icza
Another useful case for WeakHashMap
and WeakReference
is a listener registry implementation.
另一个有用的WeakHashMap
and案例WeakReference
是侦听器注册表实现。
When you create something which wants to listen to certain events, usually you register a listener, e.g.
当您创建想要监听某些事件的东西时,通常您会注册一个监听器,例如
manager.registerListener(myListenerImpl);
If the manager
stores your listener with a WeakReference
, that means you don't need to remove the register e.g. with a manager.removeListener(myListenerImpl)
because it will be automatically removed once your listener or your component holding the listener becomes unavailable.
如果manager
使用 a 存储您的侦听器WeakReference
,则意味着您不需要删除寄存器,例如使用 amanager.removeListener(myListenerImpl)
因为一旦您的侦听器或持有该侦听器的组件变得不可用,它将自动删除。
Of course you still can manually remove your listener, butif you don't or you forget it, it will not cause a memory leak, and it will not prevent your listener being garbage collected.
当然你仍然可以手动删除你的监听器,但是如果你不这样做或者你忘记了它,它不会导致内存泄漏,也不会阻止你的监听器被垃圾收集。
Where does WeakHashMap
come into the picture?
从哪里WeakHashMap
进入图片?
The listener registry which whishes to store registered listeners as WeakReference
s needs a collection to store these references. There is no WeakHashSet
implementation in the standard Java library only a WeakHashMap
but we can easily use the latter one to "implement" the functionality of the first one:
希望将注册的侦听器存储为WeakReference
s的侦听器注册表需要一个集合来存储这些引用。WeakHashSet
标准 Java 库中没有实现,WeakHashMap
但我们可以轻松地使用后一个来“实现”第一个的功能:
Set<ListenerType> listenerSet =
Collections.newSetFromMap(new WeakHashMap<ListenerType, Boolean>());
With this listenerSet
to register a new listener you just have to add it to the set, and even if it is not removed explicitly, if the listener is no longer referenced, it will be removed automatically by the JVM.
有了这个listenerSet
来注册一个新的监听器,你只需要将它添加到集合中,即使它没有被明确删除,如果监听器不再被引用,它也会被 JVM 自动删除。