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

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

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

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

有没有人有这种类型的经验? 我的担忧是否合理? 如果是这样,有人可以提出一个好的方法吗?

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

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

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

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

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

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

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

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

如果你想要轻量级和正在处理的东西,请查看谷歌collections。 例如,您可以使用MapMaker( http://google-collections.googlecode.com/svn/trunk/javadoc/index.html?com/google/common/collect/BiMap.html )制作包含Soft / Weak的地图键和值,所以它只缓存它有空间的项目(虽然你不会得到LRU)。

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

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

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