Java 的 WeakHashMap 和缓存:为什么引用键而不是值? [英] Java's WeakHashMap and caching: Why is it referencing the keys, not the values?

查看:19
本文介绍了Java 的 WeakHashMap 和缓存:为什么引用键而不是值?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

Java 的 WeakHashMap 通常被认为对缓存很有用.虽然它的弱引用是根据映射的键而不是它的值定义的,但这似乎很奇怪.我的意思是,这是我想要缓存的值,并且一旦除了缓存之外没有其他人强烈引用它们,我想要垃圾收集,不是吗?

保持对键的弱引用有什么帮助?如果你做一个 ExpensiveObject o = weakHashMap.get("some_key"),那么我希望缓存保持在 'o' 直到调用者不再持有强引用,我不根本不关心字符串对象some_key".

我错过了什么吗?

解决方案

WeakHashMap 不是用作缓存,至少大多数人认为它是这样.正如你所说,它使用弱,而不是弱,所以它不是为大多数人想要使用它而设计的(事实上,我已经看到人们错误地使用它).

WeakHashMap 主要用于保留有关其生命周期不受您控制的对象的元数据.例如,如果您有一堆对象通过您的类,并且您希望跟踪有关它们的额外数据,而无需在它们超出范围时收到通知,并且无需对它们的引用来保持它们的活动.

一个简单的例子(也是我以前用过的)可能是这样的:

WeakHashMap

您可以在哪里跟踪系统中的各种线程正在做什么;当线程终止时,条目将从您的地图中静默删除,如果您是对它的最后一个引用,则不会阻止该线程被垃圾收集.然后,您可以遍历该映射中的条目,以找出有关系统中活动线程的元数据.

参见 WeakHashMap 不是缓存! 了解更多信息.

对于您所追求的缓存类型,请使用专用缓存系统(例如 EHCache)或查看GuavaMapMaker 类;类似的东西

new MapMaker().weakValues().makeMap();

会做你想做的事,或者如果你想花哨,你可以添加定时过期:

new MapMaker().weakValues().expiration(5, TimeUnit.MINUTES).makeMap();

Java's WeakHashMap is often cited as being useful for caching. It seems odd though that its weak references are defined in terms of the map's keys, not its values. I mean, it's the values I want to cache, and which I want to get garbage collected once no-one else besides the cache is strongly referencing them, no?

In which way does it help to hold weak references to the keys? If you do a ExpensiveObject o = weakHashMap.get("some_key"), then I want the cache to hold on to 'o' until the caller doesn't hold the strong reference anymore, and I don't care at all about the string object "some_key".

Am I missing something?

解决方案

WeakHashMap isn't useful as a cache, at least the way most people think of it. As you say, it uses weak keys, not weak values, so it's not designed for what most people want to use it for (and, in fact, I've seen people use it for, incorrectly).

WeakHashMap is mostly useful to keep metadata about objects whose lifecycle you don't control. For example, if you have a bunch of objects passing through your class, and you want to keep track of extra data about them without needing to be notified when they go out of scope, and without your reference to them keeping them alive.

A simple example (and one I've used before) might be something like:

WeakHashMap<Thread, SomeMetaData>

where you might keep track of what various threads in your system are doing; when the thread dies, the entry will be removed silently from your map, and you won't keep the Thread from being garbage collected if you're the last reference to it. You can then iterate over the entries in that map to find out what metadata you have about active threads in your system.

See WeakHashMap in not a cache! for more information.

For the type of cache you're after, either use a dedicated cache system (e.g. EHCache) or look at Guava's MapMaker class; something like

new MapMaker().weakValues().makeMap();

will do what you're after, or if you want to get fancy you can add timed expiration:

new MapMaker().weakValues().expiration(5, TimeUnit.MINUTES).makeMap();

这篇关于Java 的 WeakHashMap 和缓存:为什么引用键而不是值?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆