我正在尝试在Java中实现一个LRU缓存,它应该能够:
动态改变大小。我的计划是将其作为SoftReference订阅到ReferenceQueue中。因此,缓存大小将根据内存消耗而变化。
我计划使用ConcurrentHashMap,其中值将是一个软引用,并定期清除队列以更新地图。
但上述方法的问题是,如何使其成为LRU?
我知道我们无法控制GC,但我们能否管理对值(在缓存中)的引用,以便所有可能的缓存对象都会根据使用情况(即最后访问时间),而不是以某种随机方式成为软引用(在GC下)。
我正在尝试在Java中实现一个LRU缓存,它应该能够:
动态改变大小。我的计划是将其作为SoftReference订阅到ReferenceQueue中。因此,缓存大小将根据内存消耗而变化。
我计划使用ConcurrentHashMap,其中值将是一个软引用,并定期清除队列以更新地图。
但上述方法的问题是,如何使其成为LRU?
我知道我们无法控制GC,但我们能否管理对值(在缓存中)的引用,以便所有可能的缓存对象都会根据使用情况(即最后访问时间),而不是以某种随机方式成为软引用(在GC下)。
如果您想同时拥有多个缓存,那么您的问题才有意义。如果您只有一个缓存,请不要设置大小限制,并始终使用WeakReference
。这样,缓存将自动使用所有可用的空闲内存。
然而,准备好与系统管理员进行一些激烈的讨论,因为他们会抱怨您的应用程序存在内存泄漏,并且“随时都会崩溃!”叹气
另一个选择是使用成熟的缓存库,比如EHCache,因为它已经知道关于缓存的所有内容,并花费了数年时间来完善它们。除非您想花费数年时间调试代码以使其适用于Java内存模型的每个角落案例,否则我建议您避免这次重新发明轮子。
LinkedHashMap
或编写自己的映射。Java 中没有其他地图可以限制大小。例如,Guava 使用他们自己的 CacheBuilder
来构建具有特定限制的缓存,因为 Java 运行时中没有足够的控制。 - Aaron DigullaWeakHashMap
也同样适用。 - Aaron Digulla我会使用LinkedHashMap,因为它支持访问顺序并可用作LRU映射。它可以具有可变的最大大小。
基于使用情况在弱引用和软引用之间切换非常难以正确处理,因为很难确定a)您的缓存独占使用了多少,b)系统正在使用多少,c)Full GC后将使用多少。
您应该注意,弱引用和软引用仅在GC时才会被清除,并且丢弃它们或更改它们不会在运行GC之前释放内存。
LinkedHashMap<Key, SoftReference<Value>>
吗? - Peter Lawrey