gpt4 book ai didi

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

转载 作者:塔克拉玛干 更新时间:2023-11-03 02:54:34 25 4
gpt4 key购买 nike

我希望在不做太多工作的情况下(自然地)实现一个简单的缓存。在我看来,一个标准的 Java 集合应该就足够了,只需做一些额外的工作。具体来说,我正在存储来自服务器的响应,键可以是请求 URL 字符串或从 URL 生成的哈希码。

我最初认为我可以使用 WeakHashMap,但看起来该方法迫使我管理我想要保留的对象,以及我不管理的任何对象强引用立即被清除。我应该尝试使用 SoftReference 值的 ConcurrentHashMap 吗?或者这些也会被非常积极地清理掉吗?

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

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

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

最佳答案

如果您使用基于 SoftReference 的键,VM 将(强烈)偏向最近访问的对象。然而,确定缓存语义是相当困难的 - SoftReference 给你的唯一保证(通过 WeakReference)是它OutOfMemoryError 被抛出之前被清除. JVM 实现将它们与 WeakReferences 相同地对待是完全合法的,此时您可能最终得到一个不缓存任何内容的缓存。

我不知道它在 Android 上是如何工作的,但是对于 Sun 最近的 JVM,可以使用 -XX:SoftRefLRUPolicyMSPerMB 命令行选项调整 SoftReference 行为,该选项决定软可访问对象的毫秒数保留为,堆中每 MB 的可用内存。正如您所看到的,要摆脱任何可预测的生命周期行为将异常困难,而且这个设置对于 VM 中的所有软引用都是全局的,并且不能针对个别类的使用单独调整SoftReferences(每次使用可能需要不同的参数)。


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

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

关于java - 我应该使用哪个 Java 集合来实现线程安全缓存?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3355216/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com