java - LinkedHashMap LRU 缓存 - 确定删除了哪些值?

标签 java caching lru linkedhashset

背景信息

您可以使用 LinkedHashMap 创建 LRU 缓存,如图所示 at this link .基本上,您只需:

  • 扩展链接 HashMap 。
  • 提供容量参数。
  • 使用参数初始化父类(super class) (LinkedHashMap),告诉它它的容量、比例因子(永远不应该使用),并保持项目的插入/引用顺序。
  • 覆盖 removeEldestEntry 以在超出容量时删除最早的条目。

我的问题

这是一个非常标准的 LRU 缓存实现。但是我不知道该怎么做的一件事是当 LinkedHashMap 由于最近没有足够使用而删除条目时如何得到通知。

我知道我可以让 removeEldestEntry 提供某种形式的通知...但是有什么方法可以在将新元素插入(放置)到基础 map 中时立即检索从缓存中删除的元素?或者,有没有办法查询从缓存中删除的最后一项?

最佳答案

您可以通过创造性地使用线程本地存储来让它工作:

class LRUCacheLHM<K,V> extends LinkedHashMap<K,V> {

    private int capacity;

    public LRUCacheLHM(int capacity) {
        //1 extra element as add happens before remove (101), and load factor big
        //enough to avoid triggering resize.  True = keep in access order.
        super(capacity + 1, 1.1f, true);
        this.capacity = capacity;
    }
    private ThreadLocal<Map.Entry<K,V>> removed = new ThreadLocal<Map.Entry<K,V>>();
    private ThreadLocal<Boolean> report = new ThreadLocal<Boolean>();
    {
        report.set(false);
    }
    @Override
    public boolean removeEldestEntry(Map.Entry<K,V> eldest) {
        boolean res = size() > capacity;
        if (res && report.get()) {
            removed.set(eldest);
        }
        return res;
    }
    public Map.Entry<K,V> place(K k, V v) {
        report.set(true);
        put(k, v);
        try {
            return removed.get();
        } finally {
            removed.set(null);
            report.set(false);
        }
    }

}

Demo.

place(K,V) 方法背后的想法是向 removeEldestEntry 发出信号,我们希望通过设置线程局部 来获取最老的条目>report 标志为 true。当 removeEldestEntry 看到这个标志并知道一个条目正在被删除时,它会将最老的条目放在 report 变量中,该变量也是线程本地的。

removeEldestEntry 的调用发生在对 put 方法的调用中。在那之后,最老的条目要么是 null,要么位于 report 变量中准备好被收集。

removed 上调用 set(null) 对于避免挥之不去的内存泄漏很重要。

关于java - LinkedHashMap LRU 缓存 - 确定删除了哪些值?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29946546/

相关文章:

java - "Content is not allowed in prolog"使用 JAXB 解码 JSON 时

web-services - 站点重启时缓存不明确

java - 在 Ignite 缓存中插入数据时出现以下错误?

caching - CPU中的LRU缓存是如何实现的?

java - 如何计算移动应用分析中的活跃用户?

Java 集合接口(interface),保证不重复并保留插入顺序

java - FlashScope.getCurrent(...) 始终返回新的 FlashScope 实例

php - 取消设置 php 中的变量会影响缓存吗?

python - Web API 客户端包装器的缓存算法

java - 尝试在 Java 中实现 LRU 算法时,在 LinkedHashmap 中删除 EldestEntry