Home > Software design >  Insert object to a map with ttl
Insert object to a map with ttl

Time:11-27

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/

  • Related