Search code examples
javacollectionsguavaconcurrenthashmap

google guava cachebuilder use greater of the time between exipreAfterAccess and expireActerWrite


Firstly I apolozige if I didnt adhere to any of the rules and regulations of stackoverflow as I am posting a question for the first time.

I am in a situation where I need to use expirable map where elements from the map can be deleted automatically after certain time. I am glad that i can use cachebuilder from google guava. I need to specify a default time limit which I can do by using expireAfterWrite(..) but I need to override it after my access. I can use exipreAfterAccess(..) but it still removes it after initial time set by exipreAfterWrite(..)

How can I achieve this functionality so that removal criteria checks for greater of the time between exipreAfterAccess and expireActerWrite

Thanks for looking into this


Solution

  • I would just advise on not setting the expireAfterWrite value. This will achieve exactly what you want.

    See small example below.

    1. It first illustrates your current situation (expireAfterWrite=1 second, expireAfterAccess=2 seconds)--> Every second, value is reloaded
    2. It then creates a cache with only (expireAfterAccess=2 seconds) and accesses it every 100ms-->Value is only loaded once
    3. It then sleeps for 2 seconds-->value is properly reloaded.

    import java.util.concurrent.ExecutionException;
    import java.util.concurrent.TimeUnit;
    
    import com.google.common.base.Stopwatch;
    import com.google.common.cache.CacheBuilder;
    import com.google.common.cache.CacheLoader;
    import com.google.common.cache.LoadingCache;
    
    public class TestCache {
    
        private static final String KEY = "Key";
    
        public static void main(String[] args) throws ExecutionException, InterruptedException {
            CacheLoader<String, String> loader = new CacheLoader<String, String>() {
                @Override
                public String load(String key) throws Exception {
                    System.out.println("Loading key");
                    return key;
                }
            };
            LoadingCache<String, String> cache1 = CacheBuilder.newBuilder().expireAfterAccess(2L, TimeUnit.SECONDS)
                    .expireAfterWrite(1L, TimeUnit.SECONDS).build(loader);
            cache1.get(KEY); // First write
            testCache(cache1);
            LoadingCache<String, String> cache2 = CacheBuilder.newBuilder().expireAfterAccess(2L, TimeUnit.SECONDS).build(loader);
            testCache(cache2);
            System.out.println("Final test on cache 2");
            Thread.sleep(2001);
            System.out.println(cache2.get(KEY));
    
        }
    
        private static void testCache(LoadingCache<String, String> cache1) throws ExecutionException, InterruptedException {
            Stopwatch sw = Stopwatch.createStarted();
            while (sw.elapsed(TimeUnit.SECONDS) < 5) {
                System.out.println(sw.elapsed(TimeUnit.MILLISECONDS) + " " + cache1.get(KEY));
                Thread.sleep(100);
            }
        }
    }