在番石榴中,當使用LoadingCache時,CacheLoader被同步調用。但是,我的load()
操作可能需要很長的時間(〜1秒),如果它需要太長時間(> 200 ms)並且異步加載值,我想採取默認操作。帶異步加載的LoadingCache
有沒有辦法做到這一點?或者還有其他方法可以推薦嗎?
在番石榴中,當使用LoadingCache時,CacheLoader被同步調用。但是,我的load()
操作可能需要很長的時間(〜1秒),如果它需要太長時間(> 200 ms)並且異步加載值,我想採取默認操作。帶異步加載的LoadingCache
有沒有辦法做到這一點?或者還有其他方法可以推薦嗎?
您可以按照正常的方式執行此操作:提交任務以獲取緩存值至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
}
您可以檢查是否值爲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;
}
});
我相當肯定有沒有辦法與當前的API來實現這一目標。 –