我应该使用哪个Java集合来实现线程安全缓存? [英] Which Java collection should I use to implement a thread-safe cache?

查看:143
本文介绍了我应该使用哪个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 c $ c>被抛出。对于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集合来实现线程安全缓存?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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