什么时候会使用 Wea​​kHashMap 或 WeakReference?

发布于 2024-07-06 14:50:42 字数 121 浏览 8 评论 0原文

弱引用的使用是我从未见过的实现,因此我试图弄清楚它们的用例是什么以及实现如何工作。 您何时需要使用 WeakHashMapWeakReference 以及如何使用它们?

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(10

没企图 2024-07-13 14:50:42

强引用的一个问题是
缓存,特别是非常大的
像图像这样的结构。 假设你
有一个必须运行的应用程序
使用用户提供的图像,例如
我使用的网站设计工具。
自然你想缓存这些
图像,因为从磁盘加载它们
非常昂贵,你想要
避免拥有两个的可能性
(可能是巨大的)的副本
图像立即存入内存。

因为图像缓存应该
阻止我们重新加载图像
我们绝对不需要,你会的
很快意识到缓存应该
始终包含对任何内容的引用
已经存在于内存中的图像。 和
不过,普通的强引用,
该引用本身将迫使
图像保留在内存中,其中
需要你以某种方式确定何时
不再需要该图像
内存并将其从缓存中删除,
使其有资格获得
垃圾收集。 你被迫
重复垃圾的行为
收集器并手动确定
对象是否应该位于
内存。

了解弱引用,Ethan Nicholas

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

梦里南柯 2024-07-13 14:50:42

WeakReferenceSoftReference

需要明确的一个区别是 WeakReferenceSoftReference

基本上,WeakReference 将由 GC-d一旦引用的对象没有硬引用,a href="https://en.wikipedia.org/wiki/Java_virtual_machine" rel="noreferrer">JVM 就会急切地调用它。 另一方面,软引用对象往往会被垃圾收集器留下,直到它真正需要回收内存为止。

保存在WeakReference中的缓存将毫无用处(在WeakHashMap中,弱引用的是键)。 当您想要实现可以随可用内存增长和收缩的缓存时,SoftReferences 对于包装值非常有用。

WeakReference versus SoftReference

One distinction to be clear on is the difference between a WeakReference and a SoftReference.

Basically a WeakReference will be GC-d by the JVM eagerly, once the referenced object has no hard references to it. A SoftReferenced object on the other hand, will tend to be left about by the garbage collector until it really needs to reclaim the memory.

A cache where the values are held inside WeakReferences 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.

浅暮の光 2024-07-13 14:50:42

WeakReferenceWeakHashMap 的一种常见用途是向对象添加属性。 有时您想要向对象添加一些功能或数据,但子类化和/或组合不是一个选项,在这种情况下,显而易见的做法是创建一个哈希图,将您想要扩展的对象链接到您想要添加的属性。 然后每当您需要该房产时,您只需在地图上查找即可。 但是,如果您要添加属性的对象往往会被大量销毁和创建,则最终可能会在地图中出现大量旧对象,从而占用大量内存。

如果您使用 WeakHashMap,则对象一旦不再被程序的其余部分使用,就会离开您的映射,这是所需的行为。

我必须这样做才能向 java.awt.Component 添加一些数据,以解决 JRE 在 1.4.2 和 1.5 之间的变化,我可以通过子类化我感兴趣的每个组件来修复它(JButtonJFrameJPanel....)但这更容易,代码也少得多。

One Common use of WeakReferences and WeakHashMaps 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.

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.

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.

绝情姑娘 2024-07-13 14:50:42

WeakHashMapWeakReference 的另一个有用案例是侦听器注册表实现

当你创建想要监听某些事件的东西时,通常你会注册一个监听器,例如,

manager.registerListener(myListenerImpl);

如果manager使用WeakReference存储你的监听器,这意味着你不需要例如使用manager.removeListener(myListenerImpl)删除寄存器,因为一旦您的侦听器或持有侦听器的组件不可用,它将自动删除。

当然,您仍然可以手动删除侦听器,但是如果您不这样做或忘记它,则不会导致内存泄漏,也不会阻止您的侦听器被垃圾收集。

WeakHashMap 在哪里出现?

希望将注册侦听器存储为 WeakReference 的侦听器注册表需要一个集合来存储这些引用。 标准 Java 库中没有 WeakHashSet 实现,只有一个 WeakHashMap,但我们可以轻松地使用后一个来“实现”第一个的功能:

Set<ListenerType> listenerSet =
    Collections.newSetFromMap(new WeakHashMap<ListenerType, Boolean>());

使用这个 listenerSet 要注册一个新的侦听器,您只需将其添加到集合中,即使没有显式删除它,如果不再引用该侦听器,JVM也会自动将其删除。

Another useful case for WeakHashMap and WeakReference is a listener registry implementation.

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.

Of course you still can manually remove your listener, but if 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?

The listener registry which whishes to store registered listeners as WeakReferences 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:

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.

三生路 2024-07-13 14:50:42

这篇博文演示了这两个类的用法: 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 提供基于 id 的对象进行同步。 要求是:

  • 必须返回对同一对象的引用以并发使用等效 ID
  • 必须为不同 ID 返回不同的对象
  • 无释放机制(对象不会返回给提供者)
  • 不得泄漏(未使用的对象有资格进行垃圾回收)

这是通过使用以下类型的内部存储映射来实现的:

WeakHashMap<Mutex, WeakReference<Mutex>>

对象既是键又是值。 当映射外部的任何内容都没有对该对象的硬引用时,它可以被垃圾收集。 映射中的值使用硬引用存储,因此必须将值包装在弱引用中以防止内存泄漏。 javadoc 中介绍了最后一点。

This blog post demonstrates the use of both classes: Java: synchronizing on an ID. The usage goes something like this:

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:

  • 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)

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 WeakReference to prevent a memory leak. This last point is covered in the javadoc.

面犯桃花 2024-07-13 14:50:42

例如,如果您想跟踪某个类创建的所有对象。 为了仍然允许这些对象被垃圾收集,您可以保留对对象的弱引用的列表/映射,而不是对象本身。

现在,如果有人可以向我解释幻像引用,我会很高兴......

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...

你在看孤独的风景 2024-07-13 14:50:42

如上所述,只要强引用存在,弱引用就会被保留。

一个示例用法是在侦听器内部使用 Wea​​kReference,以便一旦对目标对象的主要引用消失,侦听器就不再活动。
请注意,这并不意味着 WeakReference 已从侦听器列表中删除,清理仍然需要,但可以在例如计划的时间执行。
这还具有防止监听的对象持有强引用并最终成为内存膨胀的根源的效果。
示例:Swing GUI 组件引用的模型的生命周期比窗口更长。

在如上所述与侦听器一起玩时,我们很快意识到从用户的角度来看,对象是“立即”收集的。

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.

While playing with listeners as described above we rapidly realised that objects get collected "immediately" from a user's point of view.

梦开始←不甜 2024-07-13 14:50:42

我对 WeakReferences 的实际用途之一是,如果您有一个很少使用的非常大的对象。 当不需要它时,你不想将它保留在内存中; 但是,如果另一个线程需要同一个对象,您也不希望内存中存在两个对象。 您可以在某处保留对该对象的弱引用,并在使用该对象的方法中保留硬引用; 当两个方法都完成时,对象将被收集。

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.

国际总奸 2024-07-13 14:50:42

我用谷歌代码搜索“new WeakHashMap()”。

中得到了一堆匹配项

  1. 我从 GNU 类路径项目和Apache xbean 项目 : WeakHashMapEditor.java
  2. Apache Lucene 项目:CachingWrapperFilter.java

I did a google code search for "new WeakHashMap()".

I got a bunch of matches from the GNU classpath project and

  1. Apache xbean Project : WeakHashMapEditor.java
  2. Apache Lucene project : CachingWrapperFilter.java
秋千易 2024-07-13 14:50:42

您可以使用weakhashmap来实现无资源缓存以进行扩展对象创建。

但请注意,不希望有可变对象。
我用它来将查询结果(执行大约需要 400 毫秒)缓存到文本搜索引擎,该引擎很少更新。

you can use weakhashmap to implement a resource-free caching for expansive object creation.

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文