jub*_*ber 13 java caching dictionary memory-management fixed
是否有一个简单,高效的Map
实现,允许地图使用内存限制.
我的用例是我想动态分配创建时可用的大部分内存,但我不希望OutOFMemoryError
在将来的任何时候.基本上,我想使用这个地图作为缓存,但我想避免繁重的缓存实现,如EHCache
.我的需求很简单(最多一个LRU算法)
我应该进一步澄清我的缓存中的对象是char[]
或类似的原语,它们不会保存对其他对象的引用.
我可以为每个条目设置最大大小的上限.
pol*_*nts 10
您可以使用a LinkedHashMap
来限制以下内容中的条目数Map
:
removeEldestEntry(Map.Entry<K,V> eldest)
:true
如果此映射应删除其最旧条目,则返回.在将新条目插入地图之后put
和putAll
之后调用此方法.它为实现者提供了在每次添加新条目时删除最旧条目的机会.如果映射表示缓存,这将非常有用:它允许映射通过删除过时条目来减少内存消耗.示例使用:此覆盖将允许地图增长到100个条目,然后在每次添加新条目时删除最旧的条目,保持100个条目的稳定状态.
Run Code Online (Sandbox Code Playgroud)private static final int MAX_ENTRIES = 100; protected boolean removeEldestEntry(Map.Entry eldest) { return size() > MAX_ENTRIES; }
对于缓存,a SoftHashMap
比a更合适WeakHashMap
.当您想要保持与对象的关联时,通常使用WeakhashMap,只要该对象处于活动状态,但不会阻止它被回收.
相反,a SoftReference
更密切地涉及内存分配.请参阅否SoftHashMap?有关差异的详细信息.
WeakHashMap
通常也不合适,因为它具有围绕错误的缓存方式的关联 - 它使用弱键和硬值.也就是说,当垃圾收集器清除密钥时,密钥和值将从映射中删除.这通常不是您想要的缓存 - 其中键通常是轻量级标识符(例如字符串或其他一些简单的值类型) - 缓存通常操作使得在清除值引用时回收键/值.
Commons Collections有一个ReferenceMap
可以插入您希望用于键和值的引用类型的地方.对于对内存敏感的缓存,您可能会使用键的硬引用和值的软引用.
要获取给定数量的引用N的LRU语义,请维护从缓存中获取的最后N个条目的列表 - 当从缓存中检索条目时,将其添加到列表的头部(并且删除列表的尾部) .)为了确保不会占用太多内存,您可以创建一个软引用,并将其用作触发器,从列表末尾逐出百分比的条目.(并为下一个触发器创建一个新的软参考.)
谢谢你们的回复!
正如 jasonmp85 指出的那样,LinkedHashMap 有一个允许访问顺序的构造函数。当我查看 API 文档时,我错过了这一点。该实现看起来也相当高效(见下文)。结合每个条目的最大尺寸上限,这应该可以解决我的问题。
我还将仔细研究 SoftReference。仅供记录,Google Collections 似乎对 SoftKeys、SoftValues 和 Maps 有相当好的 API。
下面是 Java LikedHashMap 类的一个片段,展示了它们如何维护 LRU 行为。
/**
* Removes this entry from the linked list.
*/
private void remove() {
before.after = after;
after.before = before;
}
/**
* Inserts this entry before the specified existing entry in the list.
*/
private void addBefore(Entry<K,V> existingEntry) {
after = existingEntry;
before = existingEntry.before;
before.after = this;
after.before = this;
}
/**
* This method is invoked by the superclass whenever the value
* of a pre-existing entry is read by Map.get or modified by Map.set.
* If the enclosing Map is access-ordered, it moves the entry
* to the end of the list; otherwise, it does nothing.
*/
void recordAccess(HashMap<K,V> m) {
LinkedHashMap<K,V> lm = (LinkedHashMap<K,V>)m;
if (lm.accessOrder) {
lm.modCount++;
remove();
addBefore(lm.header);
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
3702 次 |
最近记录: |