LRU LinkedHashMap根据可用内存限制大小
我想创建一个LinkedHashMap,它将根据可用内存限制其大小(即当freeMemory + (maxMemory - allocatedMemory)
低于某个阈值时)。 这将用作缓存的一种forms,可能使用“最近最少使用”作为缓存策略。
我担心的是,allocateMemory还包括(我假设)未垃圾收集的数据,因此会高估估计已用内存的数量。 我担心这可能产生的意外后果。
例如,LinkedHashMap可能会继续删除项目,因为它认为没有足够的可用内存,但可用内存不会增加,因为这些已删除的项目不会立即被垃圾回收。
有没有人有这种类型的经验? 我的担忧是否合理? 如果是这样,有人可以提出一个好的方法吗?
我应该补充一点,我也希望能够“锁定”缓存,基本上说“好了,从现在开始不要因为内存使用问题而删除任何东西”。
我知道我有偏见,但我真的必须强烈推荐我们的MapMaker 。 使用softKeys()或softValues()function,具体取决于它是否为密钥的GC集合,或者是否可以清理条目时更恰当地描述的值。
缓存往往是有问题的。 IIRC,Sun的JRE中有一个SoftCache
,它遇到了很多问题。
无论如何,最简单的事情是在地图中使用SoftReference
。 只要SoftReference
和Map.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我计算每个条目的平均内存消耗并触发驱逐(异步),如果计算的内存限制>允许的内存限制。
- 当然,内存计算实际上并没有显示实际内存消耗,而是将计算内存与实际值进行比较(使用分析器),我发现它足够接近。
我打算在缓存上添加一个额外的防护,以便在出现比基于内存的驱逐更快的情况下进行驱逐,但直到现在我才发现需要这样做。