I am trying to implement some kind of map with the following characteristics.
Every item should be removed after the time-to-live has elapsed (unless time-to-live is 0 and then the item does not expire) get, put, remove, size should all have a complexity of o(1) in average
I have called a thread inside a constructor that goes in a while(true)
loop and check if the ttl has expired
the code of the thread
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;
//
}
my problem is with the while(true)
which is not very efficient especially when the map is empty or it is full of object with unlimited ttl.
CodePudding user response:
I think it is not a good design to use a thread to check continuously(use while true
), it will consume a lot of resources.
You can consider another implementation: use a timer
internally, such as a ScheduledExecutorService
, and start a timing task at the same time when inserting data. For example, the survival time of a key is 5 seconds, then start a task to be executed after 5 seconds to delete the key.
You can take a look at expiringmap.
CodePudding user response:
Looks like use case for DelayQueue. This is an implementation of BlockingQueue.
A BlockingQueue will block a thread reading from the queue until an element is present.
For a very good explanation of BlockingQueue see https://youtu.be/d3xb1Nj88pw
DelayQueue is a special kind of BlockingQueue where elements in the Queue are only visible for the reading thread when a delay has expired.
See https://howtodoinjava.com/java/multi-threading/java-delayqueue/