我应该使用哪个Java集合来实现线程安全缓存?

编程入门 行业动态 更新时间:2024-10-08 18:31:56
本文介绍了我应该使用哪个Java集合来实现线程安全缓存?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述

我正在寻求实现一个简单的缓存而不需要做太多的工作(当然)。在我看来,其中一个标准的Java集合应该足够了,只需要一些额外的工作。具体来说,我正在存储来自服务器的响应,密钥可以是请求URL字符串,也可以是从URL生成的哈希码。

I'm looking to implement a simple cache without doing too much work (naturally). It seems to me that one of the standard Java collections ought to suffice, with a little extra work. Specifically, I'm storing responses from a server, and the keys can either be the request URL string or a hash code generated from the URL.

我原本以为我是d能够使用 WeakHashMap ,但看起来该方法迫使我管理我想要保留的对象,以及我没有用强引用管理的任何对象立即被扫除。我应该尝试一下 ConcurrentHashMap 的 SoftReference 值吗?或者那些也会被积极清理?

I originally thought I'd be able to use a WeakHashMap, but it looks like that method forces me to manage which objects I want to keep around, and any objects I don't manage with strong references are immediately swept away. Should I try out a ConcurrentHashMap of SoftReference values instead? Or will those be cleaned up pretty aggressively too?

我现在正在查看 LinkedHashMap 类。通过一些修改,它看起来很有希望用于MRU缓存。还有其他任何建议吗?

I'm now looking at the LinkedHashMap class. With some modifications it looks promising for an MRU cache. Any other suggestions?

无论我使用哪个集合,我应该尝试手动修剪LRU值,还是可以信任VM偏向回收最近访问过的对象?

Whichever collection I use, should I attempt to manually prune the LRU values, or can I trust the VM to bias against reclaiming recently accessed objects?

仅供参考,我正在Android上开发,所以我不想导入任何第三方库。我正在处理一个非常小的堆(16到24 MB),因此VM可能非常渴望回收资源。我认为GC会很激进。

FYI, I'm developing on Android so I'd prefer not to import any third-party libraries. I'm dealing with a very small heap (16 to 24 MB) so the VM is probably pretty eager to reclaim resources. I assume the GC will be aggressive.

推荐答案

如果你使用 SoftReference 基于密钥,VM会(最强烈地)偏向最近访问的对象。然而,确定缓存语义是非常困难的 - SoftReference给你(通过WeakReference)的唯一保证是 在 OutOfMemoryError 被抛出。对于JVM实现来说,将它们与WeakReferences完全相同是完全合法的,此时你最终可能会得到一个不缓存任何东西的缓存。

If you use SoftReference-based keys, the VM will bias (strongly) against recently accessed objects. However it would be quite difficult to determine the caching semantics - the only guarantee that a SoftReference gives you (over a WeakReference) is that it will be cleared before an OutOfMemoryError is thrown. It would be perfectly legal for a JVM implementation to treat them identically to WeakReferences, at which point you might end up with a cache that doesn't cache anything.

我不喜欢不知道在Android上如何工作,但是使用Sun最近的JVM,可以使用-XX:SoftRefLRUPolicyMSPerMB命令行选项调整SoftReference行为,该选项确定每MB可保持软可达对象的毫秒数。堆中的空闲内存。正如您所看到的,这将是非常难以获得任何可预测的生命周期行为,更加痛苦的是,此设置对于VM中的所有软引用是全局的,并且不能单独调整以用于各个类的使用SoftReferences(每次使用的机会都需要不同的参数)。

I don't know how things work on Android, but with Sun's recent JVMs one can tweak the SoftReference behaviour with the -XX:SoftRefLRUPolicyMSPerMB command-line option, which determines the number of milliseconds that a softly-reachable object will be retained for, per MB of free memory in the heap. As you can see, this is going to be exceptionally difficult to get any predictable lifespan behaviour out of, with the added pain that this setting is global for all soft references in the VM and can't be tweaked separately for individual classes' use of SoftReferences (chances are each use will want different parameters).

制作LRU缓存的最简单方法是扩展LinkedHashMap 如此处所述。由于您需要线程安全,最初扩展它的最简单方法是使用 Collections.synchronizedMap 在此自定义类的实例上,以确保安全的并发行为。

The simplest way to make an LRU cache is by extending LinkedHashMap as described here. Since you need thread-safety, the simplest way to extend this initially is to just use Collections.synchronizedMap on an instance of this custom class to ensure safe concurrent behaviour.

注意过早优化 - 除非您需要非常高的吞吐量,否则理论上粗略同步的次优开销不太可能成为问题。好消息 - 如果分析显示由于密码锁争用导致您执行速度太慢,您将获得有关缓存运行时使用的足够信息,您将能够提供合适的无锁替代方案(可能基于ConcurrentHashMap和一些手动LRU处理)而不必猜测其负载配置文件。

Beware premature optimisation - unless you need very high throughput, the theoretically suboptimal overhead of the coarse synchronization is not likely to be an issue. And the good news - if profiling shows that you are performing too slowly due to heavy lock contention, you'll have enough information available about the runtime use of your cache that you'll be able to come up with a suitable lockless alternative (probably based on ConcurrentHashMap with some manual LRU treatment) rather than having to guess at its load profile.

更多推荐

我应该使用哪个Java集合来实现线程安全缓存?

本文发布于:2023-11-28 21:45:30,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1644045.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:来实现   线程   缓存   Java

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!