Java 如何运行定期清理列表中某些元素的后台线程?
我目前正在实现缓存。我已经完成了基本的实现,如下所示。我想做的是运行一个线程,该线程将删除满足某些条件的条目Java 如何运行定期清理列表中某些元素的后台线程?,java,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 HashSe
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);
}
....
}
类缓存{
int timeLimit=10;//访问(标记)后每个条目需要保留多长时间
int maxEntries=10;//最大条目数
HashSet=newhashset();
公共无效添加(条目t){
....
}
公共入口访问(字符串键){
//标记已使用的条目
//由于它已被标记,后台线程应在timeLimit秒后删除此条目。
返回set.get(键);
}
....
}
我的问题是,我应该如何实现后台线程,以便线程绕过集合中的条目并删除已标记的条目&&(上次访问时间-现在)>timeLimit
编辑
上面只是代码的简化版本,我并没有编写同步语句 首先,如下面的注释所示,访问您的收藏
synchronized
或使用ConcurrentHashSet
aConcurrentHashMap
basedSet
其次,编写新线程,并将其实现为一个无休止的循环,定期迭代先前的集合并删除元素。编写此类时,应该使用构造函数中正确的集合对其进行初始化,这样就不必担心“如何访问正确的集合”。为什么要重新发明轮子?(以及任何像样的缓存实现)都可以为您做到这一点。此外,更轻量级的功能还可以自动删除旧条目 如果你真的想自己实现这一点,其实并不是那么简单
ConcurrentHashMap
或synchronized
关键字来存储条目。这可能真的很棘手maxEntries
,那么首先删除哪些条目 new Thread(new Runnable() {
public void run() {
cache.cleanUp();
try { Thread.sleep(MY_SLEEP_DURATION); } catch (Exception e) {};
}
}).start();
我不认为你真的需要背景线程。相反,您可以在执行查找之前或之后删除过期的条目。这简化了整个实现,很难区分两者之间的区别
顺便说一句:如果您使用LinkedHashMap,您可以通过覆盖RemoveedStantry(参见其javadocs示例)将其用作LRU缓存。首先,您提供的代码是不完整的,因为
哈希集上没有get(key)
(因此我假设您指的是某种Map
),并且您的代码没有提到任何内容“标记。”还有很多方法可以进行缓存,在不知道要缓存什么以及为什么要缓存的情况下,很难选择最佳解决方案
在实现缓存时,通常假设数据结构将由多个线程并发访问。因此,您需要做的第一件事是使用线程安全的备份数据结构。HashMap
不是线程安全的,但是ConcurrentHashMap
是线程安全的。还有许多其他的缓冲区rrentMap
实现,即,和。除了Map之外,还有其他方法来构建缓存,它们的有用性取决于您的用例。不管怎样,您很可能需要使备份数据结构线程安全,即使您决定不需要后台线程,而是在一次更新时逐出过期的对象尝试从缓存中检索条目。或者让GC使用SoftReference
s删除条目
一旦使缓存线程的内部安全,就可以启动一个新的(很可能是守护)线程,定期扫描/迭代缓存并删除旧条目。该线程将在循环中执行此操作(直到中断,如果希望再次停止),然后在每次扫描后休眠一段时间
但是,你应该考虑是否值得你自己构建缓存实现。编写线程安全代码并不容易,我建议你在尝试编写自己的缓存实现之前先研究一下它。我可以在实践中推荐java并发。
当然,更简单的方法是使用现有的缓存实现
- 这两种缓存都是通用的,可以满足典型“企业”应用程序中的大多数缓存需求
- 是一个为分布式使用而优化的缓存,因此可以缓存比一台机器上可以容纳的数据更多的数据。我也喜欢它的
ConcurrentMa