LRU LinkedHashMap根据可用内存限制大小

时间:2009-10-29 20:13:23

标签: java garbage-collection memory-management

我想创建一个LinkedHashMap,它将根据可用内存限制其大小(即freeMemory + (maxMemory - allocatedMemory)低于某个阈值时)。这将用作一种缓存形式,可能使用“最近最少使用”作为缓存策略。

我担心的是,allocateMemory还包括(我假设)非垃圾收集数据,因此会高估估计已用内存的数量。我担心这可能会产生意想不到的后果。

例如,LinkedHashMap可能会继续删除项目,因为它认为没有足够的可用内存,但可用内存不会增加,因为这些已删除的项目不会立即被垃圾回收。

有没有人对这类事有经验?我的顾虑值得关注吗?如果是这样,有人可以建议一个好方法吗?

我应该补充一点,我也希望能够“锁定”缓存,基本上说“好了,从现在开始不要因为内存使用问题而删除任何内容”。

5 个答案:

答案 0 :(得分:1)

我知道我有偏见,但我真的必须强烈推荐我们的MapMaker。使用softKeys()或softValues()功能,具体取决于它是否为密钥的GC集合,或者是否可以清理条目时更恰当地描述的值。

答案 1 :(得分:0)

缓存往往存在问题。 IIRC,Sun的JRE中有一个SoftCache,它遇到了很多问题。

无论如何,最简单的方法是在地图中使用SoftReference。只要SoftReferenceMap.Entry的开销明显低于缓存数据,这应该可以正常工作。

或者,您可以像WeakHashMap一样使用ReferenceQueue并轮询它或在其上有一个线程阻塞(不幸的是,每个实例一个线程)。小心同步问题。

“锁定”地图,您可能希望在必要时避免使用。您需要保留对所有数据的强引用(如果不为null则逐出)。那将是丑陋的。

答案 2 :(得分:0)

我强烈建议使用像Ehcache这样的东西,而不是重新发明一个缓存系统。它使用起来非常简单,非常易于配置,效果很好。

答案 3 :(得分:0)

正如matt b所说,像Ehcache或JbossCache这样的东西是很好的第一步。

如果你想要轻量级和正在处理的东西,请查看谷歌收藏。例如,您可以使用MapMaker(http://google-collections.googlecode.com/svn/trunk/javadoc/index.html?com/google/common/collect/BiMap.html)创建具有Soft / Weak键和值的映射,因此它只会缓存它有空间的项目(尽管您不会获得LRU)。

答案 4 :(得分:0)

我过去也有同样的需求,这就是我实现缓存的方式:

  • 有一个缓存内存管理器,它具有最小和最大内存限制(无论如何最大限制)
  • 每个注册的缓存都有以下(重要)参数:最大容量(大多数时候你有一个更高的限制,你不希望持有超过X项)&内存使用百分比
  • 我使用LinkedHashMap和ReentrantReadWriteLock来保护缓存。
  • 每次X放置我计算每个条目的平均内存消耗并且如果计算的内存限制> 1,则触发驱逐(异步)。允许内存限制。
  • 当然内存计算实际上并没有显示实际内存消耗,而是将计算内存与实际值进行比较(使用分析器)我发现它足够接近。

我打算在缓存上添加一个额外的防护,以便在出现比基于内存的驱逐更快的情况下进行驱逐,但直到现在我才发现需要这样做。