How to automatically refresh Cache using Google Guava?

前端 未结 5 1519
滥情空心
滥情空心 2020-12-23 20:39

I am using Google Guava library for caching. For automatic cache refresh we can do as follows:

cache = CacheBuilder.newBuilder()               
                      


        
相关标签:
5条回答
  • 2020-12-23 20:47

    Can you reload the cache value automatically using the below code snippet, without calling the refresh method ??

    cacher =
            CacheBuilder.newBuilder()
                .refreshAfterWrite(10, TimeUnit.SECONDS)
              .build(CacheLoader.asyncReloading(new CacheLoader<String, String>() {
    
                  @Override
                  public String load(String key) throws Exception {
                    return method-call();
                  }
                }, Executors.newSingleThreadExecutor()));
    
    0 讨论(0)
  • 2020-12-23 20:56

    JAVA 8 version with parallel stream:

    Executors
            .newSingleThreadScheduledExecutor()
            .scheduleWithFixedDelay(() -> configurationCache
                    .asMap()
                    .keySet()
                    .parallelStream()
                    .forEach((key) -> configurationCache.refresh(key)),
                0,
                1, TimeUnit.SECONDS);
    
    0 讨论(0)
  • 2020-12-23 21:03

    1st question. Use a scheduled executor to kick off a periodic refresh.

    2nd question. If you can infer your expiration policy from you cache key, or the previously cached value, it is possible to refresh you data at varying intervals.

    based on this: https://code.google.com/p/guava-libraries/wiki/CachesExplained#Refresh

    LoadingCache<Key, Graph> graphs = CacheBuilder.newBuilder()
       .refreshAfterWrite(1, TimeUnit.MINUTES)
       .build(
           new CacheLoader<Key, Graph>() {
             public Graph load(Key key) { // no checked exception
               return getGraphFromDatabase(key);
             }
    
             public ListenableFuture<Graph> reload(final Key key, Graph prevGraph) {
               if (!needsRefresh(key,prevGraph)) {
                 return Futures.immediateFuture(prevGraph);
               } else {
                 // asynchronous!
                 ListenableFutureTask<Graph> task = ListenableFutureTask.create(new Callable<Graph>() {
                   public Graph call() {
                     return getGraphFromDatabase(key);
                   }
                 });
                 executor.execute(task);
                 return task;
               }
             }
           });
    
    ScheduledExecutorService ses = Executors.newSingleThreadScheduledExecutor();
    ses.scheduleWithFixedDelay(
        new Runnable() {
            public void run() {
                for (Key key : graphs.asMap().keySet()) {
                    graphs.refresh(key);
                }
            }
        }, 0, UPDATE_INTERVAL, TimeUnit.MINUTES);
    
    0 讨论(0)
  • 2020-12-23 21:03

    Here is some sample code to refresh a cache. Guava cache is easy to implement and also it is fast.

    import java.util.concurrent.ExecutionException
    import java.util.concurrent.TimeUnit;
    
    import com.google.common.cache.CacheBuilder;
    import com.google.common.cache.CacheLoader;
    import com.google.common.cache.LoadingCache;
    
    public class GuavaTest {
        private static GuavaTest INSTANCE = new GuavaTest();
    
        public static GuavaTest getInstance(){
            return INSTANCE;
        }   
    
        private LoadingCache<String,String> cache;
    
        private GuavaTest() {
            cache = CacheBuilder.newBuilder()
                    .refreshAfterWrite(2,TimeUnit.SECONDS)
                    .build(new CacheLoader<String, String>() {
                            @Override
                            public String load(String arg0) throws Exception {
                                return addCache(arg0);
                            }
                    });
        }
    
        private String addCache(String arg0) {
            System.out.println("Adding Cache");
            return arg0.toUpperCase();
        }
    
        public String getEntry(String args) throws ExecutionException{
            System.out.println(cache.size());
            return cache.get(args);
        }
    
        public static void main(String[] args) {
            GuavaTest gt = GuavaTest.getInstance();
            try {
                System.out.println(gt.getEntry("java"));
                System.out.println(gt.getEntry("java"));
                Thread.sleep(2100);
                System.out.println(gt.getEntry("java"));
                System.out.println(gt.getEntry("java"));
            } catch (ExecutionException e) {
                e.printStackTrace();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    
    }
    

    I referred this article guava cache example

    0 讨论(0)
  • 2020-12-23 21:04

    Guava provides no way to refresh the cache in bulk, but you can schedule a periodic refresh yourself:

    LoadingCache<K, V> cache = CacheBuilder.newBuilder()
            .refreshAfterWrite(15, TimeUnit.MINUTES)
            .maximumSize(100)
            .build(new MyCacheLoader());
    
    for (K key : cache.asMap().keySet()) {
        cache.refresh(key);
    }
    

    But in that case you may want to override the CacheLoader.reload(K, V) method in MyCacheLoader so it performs asynchronously.

    As for the second question, no, you cannot set a per-entry expiration in Guava.

    0 讨论(0)
提交回复
热议问题