2013-07-03 52 views
1

在番石榴中,當使用LoadingCache時,CacheLoader被同步調用。但是,我的load()操作可能需要很長的時間(〜1秒),如果它需要太長時間(> 200 ms)並且異步加載值,我想採取默認操作。帶異步加載的LoadingCache

有沒有辦法做到這一點?或者還有其他方法可以推薦嗎?

+0

我相當肯定有沒有辦法與當前的API來實現這一目標。 –

回答

3

您可以按照正常的方式執行此操作:提交任務以獲取緩存值至ExecutorService,在Future上調用get(200, MILLISECONDS),如果超時則執行其他操作。

例子:

final LoadingCache<Key, Result> cache = ... 
final Key key = ... 
ExecutorService executor = ... 

Future<Result> future = executor.submit(new Callable<Result>() { 
    @Override public Result call() throws Exception { 
    return cache.get(key); 
    } 
}); 

try { 
    Result result = future.get(200, TimeUnit.MILLISECONDS); 
    // got the result; do stuff 
} catch (TimeoutException timeout) { 
    // timed out; take default action 
} 
+0

你能提供一些代碼片段來解釋這個想法嗎?我完全不完全理解 – aamir

+0

@AamirKhan:增加了一個簡化的例子。 – ColinD

+0

感謝ColidD! :) – aamir

1

您可以檢查是否值爲null與getIfPresent命令。 如果該值爲null,則可以提交異步加載值並繼續執行流程的任務。

例如:

Map<String, String> map = cache.getIfPresent(key); 
if(map == null){ 
executorService.submit(new Callable<Map<String, String>>() { 
    @Override 
    public Map<String, String> call() throws Exception { 
     return cache.get(key); 
    } 
}); 
} 
else{ 
    continue with the flow... 
} 

,你也應該使用refreshAfterWrite功能,如果你想刷新緩存中的值,而你還在讀舊值實現重載方法。 通過這種方式,緩存將始終更新,讀取值的主線程不會受到影響。

例如:

cache = CacheBuilder.newBuilder() 
    .refreshAfterWrite(30, TimeUnit.SECONDS) 
    .build( 
     new CacheLoader<String, Map<String,String>>() { 

      public Map<String, String> load(String key) throws Exception { 
       map = hardWork(key)//get map from from DB -- expensive time commend 
       return map; 
      } 

      @Override 
       public ListenableFuture<Map<String, String>> reload(final String key, Map<String, String> oldValue) throws Exception { 
        // we need to load new values asynchronously, so that calls to read values from the cache don't block 
        ListenableFuture<Map<String, String>> listenableFuture = executorService.submit(new Callable<Map<String, String>>() { 

         @Override 
         public Map<String, String> call() throws Exception { 
          //Async reload event 
          return load(key); 
         } 
        }); 

        return listenableFuture; 
       } 
    });