I know there is a WeakHashMap in java.util, but since it uses WeakReferences for everything, which is only referenced by this Map, referenced objects will get lost on the next GC cycle. So it's nearly useless if you want to cache random data, which is very likely to be requested again without being Hard-linked the rest of the time. The best solution would be a map, which uses SoftReferences instead, but i didn't find one in the Java RT Package.
我知道java.util中有一个WeakHashMap,但由于它只使用了WeakReferences(仅由此Map引用),因此引用的对象将在下一个GC循环中丢失。因此,如果您想要缓存随机数据,这几乎是无用的,这很可能会再次被请求而不会在其余时间进行硬链接。最好的解决方案是使用SoftReferences的map,但我没有在Java RT Package中找到一个。
6 个解决方案
#1
24
Edit (Aug. 2012):
编辑(2012年8月):
It turns out that currently the best solution are probably Guava 13.0's Cache
classes, explained on Guava's Wiki - that's what I'm going to use. It even supports building a SoftHashMap
(see CacheBuilder.newBuilder().softKeys()
), but it is probably not what you want, as Java expert Jeremy Manson explains (below you'll find the link).
事实证明,目前最好的解决方案可能是Guava 13.0的Cache类,在Guava的Wiki上解释 - 这就是我将要使用的。它甚至支持构建一个SoftHashMap(参见CacheBuilder.newBuilder()。softKeys()),但它可能不是你想要的,正如Java专家Jeremy Manson解释的那样(下面你会找到链接)。
Not that I know of (Nov. 2008), but you kind find some implementation of SoftHashMap
on the net.
不是我所知道的(2008年11月),但你在网上找到了一些SoftHashMap的实现。
Like this one: SoftHashMap
or this one.
像这样:SoftHashMap或者这个。
Edit (Nov. 2009)
As Matthias mentions in the comments, the Google Guava MapMaker does use SoftReferences:
编辑(2009年11月)正如Matthias在评论中提到的那样,Google Guava MapMaker确实使用了SoftReferences:
A
ConcurrentMap
builder, providing any combination of these features:ConcurrentMap构建器,提供以下功能的任意组合:
- soft or weak keys,
- 软键或弱键,
- soft or weak values,
- 软弱值,
- timed expiration, and
- 定时到期,和
- on-demand computation of values.
- 按需计算值。
As mentioned in this thread, another JSR166y candidate:
正如在这个帖子中提到的,另一个JSR166y候选人:
jsr166y.ConcurrentReferenceHashMap
jsr166y.ConcurrentReferenceHashMap
It provides an alternative concurrent reference map to the Google implementation (which relies on a background thread to evict entries)
它为Google实现提供了一个替代的并发参考映射(它依赖于后台线程来驱逐条目)
Edit (August 2012)
编辑(2012年8月)
The Google implementation uses a background thread only when timed expiration of entries is requested. In particular, it simply uses java.util.Timer
, which is not so intrusive as having a separate background thread.
只有在请求的条目到期时,Google实施才会使用后台线程。特别是,它只使用java.util.Timer,它不像具有单独的后台线程那样具有侵入性。
Jeremy Manson recommends, for any cache, using this feature to avoid the dangers of SoftReference: http://jeremymanson.blogspot.de/2009/07/how-hotspot-decides-to-clear_07.html
对于任何缓存,Jeremy Manson建议使用此功能来避免SoftReference的危险:http://jeremymanson.blogspot.de/2009/07/how-hotspot-decides-to-clear_07.html
There's another implementation from Apache Commons, namely org.apache.commons.collections.map.ReferenceMap; it does not support timed removal, but it does support choosing whether keys should be compared by identity or by equality. Moreover, this implementation is not concurrent - it can be made synchronized, but that works less well under accesses from multiple threads.
Apache Commons还有另一个实现,即org.apache.commons.collections.map.ReferenceMap;它不支持定时删除,但它确实支持选择是通过标识还是通过相等来比较密钥。此外,此实现不是并发的 - 它可以进行同步,但在多线程访问时效果不佳。
#2
20
I am familiar with two libraries that offer a SoftHashMap implementation:
我熟悉两个提供SoftHashMap实现的库:
-
Apache Commons: org.apache.commons.collections.map.ReferenceMap
Apache Commons:org.apache.commons.collections.map.ReferenceMap
-
Google Collections: com.google.common.collect.ReferenceMap
Google Collections:com.google.common.collect.ReferenceMap
#3
2
There is an example implementation in 98 issue of java specialists newsletter
在98期的java专家通讯中有一个示例实现
#4
#5
2
Have you considered using an LRUMap instead of a soft HashMap? You get more control over what gets stored (or at least, how much).
您是否考虑过使用LRUMap而不是软HashMap?您可以更好地控制存储的内容(或至少是多少)。
#6
1
If you want to implement a cache softreferences are definetly a better idea than weak references, but it puts your entire cache removal policy in the hands of the garbage collector. which is probably not what you want.
如果你想实现缓存,那么软引用肯定比弱引用更好,但它会将整个缓存删除策略放在垃圾收集器的手中。这可能不是你想要的。
If cache removal policy is important your are going to need to do it on your own most likely using regular references. However you are going to have to decide when to eject items and which to eject. If you only want to lose things when you are running out of heap space you can query available heap space via:
如果缓存删除策略很重要,那么您最需要使用常规引用来自行完成。但是,您将不得不决定何时弹出项目以及要弹出的项目。如果您只想在堆空间不足时丢失东西,可以通过以下方式查询可用堆空间:
Runtime.getRuntime().getFreeMemory();
Then once free memory drops below a certain amount you can start either dropping items. Or you could just implement a max size for the cache and use that to decide when to drop things.
然后,一旦空闲内存低于一定数量,您就可以开始丢弃项目。或者您可以只为缓存实现最大大小,并使用它来决定何时删除内容。
here's an LRU cache i designed with O(1) insertion, deletion and lookup time, that has a configurable max number of elements. If you want a cache this is going to be a better solution imho than a SoftHashMap.
这是一个LRU缓存,我设计了O(1)插入,删除和查找时间,具有可配置的最大元素数。如果你想要一个缓存,这将是一个比SoftHashMap更好的解决方案。
The softreferences are a great way to create a growable cache. So the ideal solution would be to use a SoftHashMap along with a regular fixed size cache. have all inserts into the cache go into both the fixed cache and the soft hash map then to reference something just see if its in the soft hashmap (and update the reference time in the cache). this way all your most important items (according to your chosen policy LRU, MFU,...) will never be removed because they are hard referenced in the cache but you will also hold on to more things (with no policy control) as long as there is sufficient memory.
软引用是创建可扩展缓存的好方法。所以理想的解决方案是使用SoftHashMap和常规固定大小的缓存。将所有插入到缓存中的内容都放入固定缓存和软哈希映射中,然后引用某些东西,看它是否在软散列映射中(并更新缓存中的引用时间)。通过这种方式,所有最重要的项目(根据您选择的策略LRU,MFU,...)将永远不会被删除,因为它们在缓存中被硬引用,但您也将保留更多内容(没有策略控制)因为有足够的记忆。
#1
24
Edit (Aug. 2012):
编辑(2012年8月):
It turns out that currently the best solution are probably Guava 13.0's Cache
classes, explained on Guava's Wiki - that's what I'm going to use. It even supports building a SoftHashMap
(see CacheBuilder.newBuilder().softKeys()
), but it is probably not what you want, as Java expert Jeremy Manson explains (below you'll find the link).
事实证明,目前最好的解决方案可能是Guava 13.0的Cache类,在Guava的Wiki上解释 - 这就是我将要使用的。它甚至支持构建一个SoftHashMap(参见CacheBuilder.newBuilder()。softKeys()),但它可能不是你想要的,正如Java专家Jeremy Manson解释的那样(下面你会找到链接)。
Not that I know of (Nov. 2008), but you kind find some implementation of SoftHashMap
on the net.
不是我所知道的(2008年11月),但你在网上找到了一些SoftHashMap的实现。
Like this one: SoftHashMap
or this one.
像这样:SoftHashMap或者这个。
Edit (Nov. 2009)
As Matthias mentions in the comments, the Google Guava MapMaker does use SoftReferences:
编辑(2009年11月)正如Matthias在评论中提到的那样,Google Guava MapMaker确实使用了SoftReferences:
A
ConcurrentMap
builder, providing any combination of these features:ConcurrentMap构建器,提供以下功能的任意组合:
- soft or weak keys,
- 软键或弱键,
- soft or weak values,
- 软弱值,
- timed expiration, and
- 定时到期,和
- on-demand computation of values.
- 按需计算值。
As mentioned in this thread, another JSR166y candidate:
正如在这个帖子中提到的,另一个JSR166y候选人:
jsr166y.ConcurrentReferenceHashMap
jsr166y.ConcurrentReferenceHashMap
It provides an alternative concurrent reference map to the Google implementation (which relies on a background thread to evict entries)
它为Google实现提供了一个替代的并发参考映射(它依赖于后台线程来驱逐条目)
Edit (August 2012)
编辑(2012年8月)
The Google implementation uses a background thread only when timed expiration of entries is requested. In particular, it simply uses java.util.Timer
, which is not so intrusive as having a separate background thread.
只有在请求的条目到期时,Google实施才会使用后台线程。特别是,它只使用java.util.Timer,它不像具有单独的后台线程那样具有侵入性。
Jeremy Manson recommends, for any cache, using this feature to avoid the dangers of SoftReference: http://jeremymanson.blogspot.de/2009/07/how-hotspot-decides-to-clear_07.html
对于任何缓存,Jeremy Manson建议使用此功能来避免SoftReference的危险:http://jeremymanson.blogspot.de/2009/07/how-hotspot-decides-to-clear_07.html
There's another implementation from Apache Commons, namely org.apache.commons.collections.map.ReferenceMap; it does not support timed removal, but it does support choosing whether keys should be compared by identity or by equality. Moreover, this implementation is not concurrent - it can be made synchronized, but that works less well under accesses from multiple threads.
Apache Commons还有另一个实现,即org.apache.commons.collections.map.ReferenceMap;它不支持定时删除,但它确实支持选择是通过标识还是通过相等来比较密钥。此外,此实现不是并发的 - 它可以进行同步,但在多线程访问时效果不佳。
#2
20
I am familiar with two libraries that offer a SoftHashMap implementation:
我熟悉两个提供SoftHashMap实现的库:
-
Apache Commons: org.apache.commons.collections.map.ReferenceMap
Apache Commons:org.apache.commons.collections.map.ReferenceMap
-
Google Collections: com.google.common.collect.ReferenceMap
Google Collections:com.google.common.collect.ReferenceMap
#3
2
There is an example implementation in 98 issue of java specialists newsletter
在98期的java专家通讯中有一个示例实现
#4
2
Apache Shiro comes with a SoftHashMap designed for caching. Its based on the article posted by jb above and licensed under Apache v2. You can find the documentation here and the source code here.
Apache Shiro附带了一个专为缓存设计的SoftHashMap。它基于上面jb发布的文章,并在Apache v2下获得许可。您可以在此处找到文档和源代码。
#5
2
Have you considered using an LRUMap instead of a soft HashMap? You get more control over what gets stored (or at least, how much).
您是否考虑过使用LRUMap而不是软HashMap?您可以更好地控制存储的内容(或至少是多少)。
#6
1
If you want to implement a cache softreferences are definetly a better idea than weak references, but it puts your entire cache removal policy in the hands of the garbage collector. which is probably not what you want.
如果你想实现缓存,那么软引用肯定比弱引用更好,但它会将整个缓存删除策略放在垃圾收集器的手中。这可能不是你想要的。
If cache removal policy is important your are going to need to do it on your own most likely using regular references. However you are going to have to decide when to eject items and which to eject. If you only want to lose things when you are running out of heap space you can query available heap space via:
如果缓存删除策略很重要,那么您最需要使用常规引用来自行完成。但是,您将不得不决定何时弹出项目以及要弹出的项目。如果您只想在堆空间不足时丢失东西,可以通过以下方式查询可用堆空间:
Runtime.getRuntime().getFreeMemory();
Then once free memory drops below a certain amount you can start either dropping items. Or you could just implement a max size for the cache and use that to decide when to drop things.
然后,一旦空闲内存低于一定数量,您就可以开始丢弃项目。或者您可以只为缓存实现最大大小,并使用它来决定何时删除内容。
here's an LRU cache i designed with O(1) insertion, deletion and lookup time, that has a configurable max number of elements. If you want a cache this is going to be a better solution imho than a SoftHashMap.
这是一个LRU缓存,我设计了O(1)插入,删除和查找时间,具有可配置的最大元素数。如果你想要一个缓存,这将是一个比SoftHashMap更好的解决方案。
The softreferences are a great way to create a growable cache. So the ideal solution would be to use a SoftHashMap along with a regular fixed size cache. have all inserts into the cache go into both the fixed cache and the soft hash map then to reference something just see if its in the soft hashmap (and update the reference time in the cache). this way all your most important items (according to your chosen policy LRU, MFU,...) will never be removed because they are hard referenced in the cache but you will also hold on to more things (with no policy control) as long as there is sufficient memory.
软引用是创建可扩展缓存的好方法。所以理想的解决方案是使用SoftHashMap和常规固定大小的缓存。将所有插入到缓存中的内容都放入固定缓存和软哈希映射中,然后引用某些东西,看它是否在软散列映射中(并更新缓存中的引用时间)。通过这种方式,所有最重要的项目(根据您选择的策略LRU,MFU,...)将永远不会被删除,因为它们在缓存中被硬引用,但您也将保留更多内容(没有策略控制)因为有足够的记忆。