使用ttl将对象插入到地图中



我正在尝试实现具有以下特性的某种映射。

每个项目都应该在生存时间结束后删除(除非生存时间为0,然后该项目没有过期(在平均中,get、put、remove、size的复杂度都应该为o(1(

我在while(true)循环中调用了构造函数中的一个线程,并检查ttl是否已过期

线程的代码

class ttlWatchdog extends Thread {
@SneakyThrows
@Override
public void run() {
long timeToSleep ;
System.out.println("Initiating Cleaner Thread..");
while (true) {
timeToSleep = checkExpiredKeys();//need to change it to a diffrent
//System.out.println("thread will sleep for  " + timeToSleep + "msc" );
Thread.sleep(timeToSleep);
}
}
public long checkExpiredKeys() throws BadParameterException {
// Just remove if timeToLive has been set before...
long timeToWake = 0;
long currentTime = System.currentTimeMillis();
int counter =0 ;
Set<Map.Entry<String, ObjectTimeStampPair> >s = valuesMap.entrySet().stream().filter(a-> a.getValue().getTtl()!=0).collect(Collectors.toSet());
for (Map.Entry<String, ObjectTimeStampPair> e : s) {
long timeItShouldRemove = e.getValue().getTtl();
if ((currentTime ) >= timeItShouldRemove) {
remove(e.getKey());
}else {// we need to take the minimum for the while loop everything here is bigger than current time i need to find the minumum
if (counter == 0 ){ // if it is the first element take it
timeToWake = e.getValue().getTtl();
counter ++;
}
else if (timeToWake > timeItShouldRemove){
timeToWake = timeItShouldRemove;
}
}
}
long result = timeToWake !=0 ? timeToWake -currentTime : 0 ;
//System.out.print("the time to wake is " +  timeToWake + " the current time is " + currentTime + " and the result is " +   result);
return result;
//
}

我的问题是while(true),它不是很有效,尤其是当映射为空或充满了具有无限ttl的对象时。

看起来像DelayQueue的用例。这是BlockingQueue的一个实现。

BlockingQueue将阻止线程从队列中读取,直到出现元素为止。

有关BlockingQueue的详细说明,请参阅https://youtu.be/d3xb1Nj88pw

DelayQueue是一种特殊类型的BlockingQueue,其中队列中的元素只有在延迟过期时才对读取线程可见。

请参阅https://howtodoinjava.com/java/multi-threading/java-delayqueue/

我认为使用线程连续检查(使用while true(不是一个好的设计,它会消耗大量资源。

您可以考虑另一种实现:在内部使用timer,例如ScheduledExecutorService,并在插入数据的同时启动计时任务。例如,密钥的生存时间为5秒,然后在5秒后启动要执行的任务以删除该密钥。

你可以看看expiringmap。

编辑,通常有以下几种方法,从Java基于时间的映射/具有过期密钥的缓存,

A。每次使用此映射时都执行清理操作。例如,线程调用map#size()map#get()map.put()。此外,您可以使用另一个DelayQueue,这将更加高效。参考:https://gist.github.com/pcan/16faf4e59942678377e0或PassiveExpiringMap

B。使用看门狗检查,每次检查后sleep一段时间。参考:apache#mina-org.apache.mina.util.ExpiringMap

C.使用timer:expiringmap。

最新更新