实现最近使用的对象缓存的最佳方法是什么?
以下是要求和限制......
答案 0 :(得分:22)
Java Collections提供开箱即用的LinkedHashMap,非常适合构建缓存。你可能在Java ME中没有这个,但你可以在这里获取源代码:
http://kickjava.com/src/java/util/LinkedHashMap.java.htm
如果你不能只是复制粘贴它,看它应该让你开始实现一个包含在你的移动应用程序中。基本思想是通过地图元素包含链表。如果您在有人放置或获取时保持更新,您可以有效地跟踪访问顺序和使用顺序。
文档包含通过覆盖removeEldestEntry(Map.Entry)
方法构建MRU Cache的说明。你真正需要做的就是创建一个扩展LinkedHashMap
的类并覆盖这样的方法:
private static final int MAX_ENTRIES = 100;
protected boolean removeEldestEntry(Map.Entry eldest) {
return size() > MAX_ENTRIES;
}
还有一个constructor,可让您指定是否希望课程通过插入或使用来按顺序存储内容,因此您的驱逐政策也有一点灵活性:
public LinkedHashMap(int initialCapacity,
float loadFactor,
boolean accessOrder)
将 true 用于使用订单,将 false 传递给广告订单。
答案 1 :(得分:7)
由于锁定要求,很难构建ConcurrentLinkedHashMap。带锁的LinkedHashMap很简单,但并不总是高效。并发版本将尝试通过锁定拆分或理想地使CAS操作使锁定非常便宜来减少锁定量。如果CAS操作变得昂贵,那么类似的桶拆分可能会有所帮助。由于LRU需要对每个访问操作进行写操作,并使用双向链表,因此使用纯CAS操作实现这一点非常棘手。我试过了,但我需要继续成熟我的算法。如果您搜索ConcurrentLinkedHashMap,您将看到我的项目页面......
如果Java ME不支持CAS操作,我希望它是真的,那么就可以进行基本同步。鉴于我在服务器端只看到高线程数的性能问题,这对于LHM来说可能已经足够了。所以+1上面的答案。
答案 2 :(得分:2)
为什么要实施已实施的内容?使用Ehcache。
然而,如果第三方库完全不可能,我想您正在寻找实现如下所示的数据结构:
HashMap<Object, Object>
)O(1)
O(1)
答案 3 :(得分:0)
另一种方法可能是看看Brian Goetz撰写的 Java Concurrency in Practice 中的5.6节:“构建一个高效,可扩展的结果缓存”。请看一下Memoizer,尽管您可能需要根据自己的需要对其进行自定义。
顺便说一下,我无法弄清楚为什么Java没有开箱即用的ConcurrentLinkedHashMap。这种数据结构对于构建缓存非常有用。