如何运行后台线程定期清理列表中的某些元素?

use*_*594 3 java

我目前正在实施缓存.我已完成基本实现,如下所示.我想要做的是运行一个线程,删除满足特定条件的条目.

class Cache {
    int timeLimit = 10; //how long each entry needs to be kept after accessed(marked)
    int maxEntries = 10; //maximum number of Entries
    HashSet<String> set = new HashSet<String>();   
    public void add(Entry t){
        ....
    }

    public Entry access(String key){
        //mark Entry that it has been used
        //Since it has been marked, background thread should remove this entry after timeLimit seconds.
        return set.get(key);
    }
    ....
}
Run Code Online (Sandbox Code Playgroud)

我的问题是,我应该如何实现后台线程,以便线程绕过集合中的条目并删除已经存在的条目marked && (last access time - now)>timeLimit

编辑

上面只是代码的简化版本,我没有写同步语句.

Tom*_*icz 8

你为什么重新发明轮子?EhCache(以及任何体面的缓存实现)都会为您完成此任务.也更轻巧MapMaker Cache来自Guava可以自动删除旧条目.

如果你真的想自己实现它,那就不是那么简单了.

  1. 记住同步.您应该使用ConcurrentHashMapsynchronized关键字来存储条目.这可能真的很棘手.

  2. 你必须以某种方式存储每个条目的最后访问时间.每次访问条目时,都必须更新该时间戳.

  3. 想想驱逐政策.如果maxEntries缓存中有多个,首先要删除哪些?

  4. 你真的需要一个后台线程吗?

    这是令人惊讶的,但EhCache(企业就绪且经过验证)不使用后台线程来使旧条目无效).相反,它会等到地图已满并懒惰地删除条目.这看起来是一个很好的权衡,因为线程很昂贵.

  5. 如果你有一个后台线程,那么每个缓存还是一个全局?您是在创建新缓存时启动新线程还是拥有所有缓存的全局列表?这比你想象的要难......

一旦你回答了所有这些问题,实现就相当简单了:每隔一秒左右查看所有条目,如果满足你已编写的条件,则删除条目.

  • 更不用说一旦你有一个线程,它将持有一个强大的引用,将产生泄漏(除非你确保在睡眠时只保持一个弱引用) (2认同)