我非常喜欢Guava 11的CacheLoader(感谢Google!)的两件事是loadAll(),它允许我一次加载多个键,以及reload(),它允许我在“陈旧”时异步重新加载一个键“但存在旧的价值。我很好奇他们如何一起玩,因为reload()只能操作一个键。
具体而言,从CachesExplained扩展示例:
LoadingCache<Key, Graph> graphs = CacheBuilder.newBuilder()
.maximumSize(1000)
.refreshAfterWrite(1, TimeUnit.MINUTES)
.build(
new CacheLoader<Key, Graph>() {
public Graph load(Key key) { // no checked exception
return getGraphFromDatabase(key);
}
public Map<Key, Graph> loadAll(Iterable<? extends K> keys) {
return getAllGraphsFromDatabase(keys);
}
public ListenableFuture<Graph> reload(final Key key, Graph prevGraph) {
if (neverNeedsRefresh(key)) {
return Futures.immediateFuture(prevGraph);
} else {
// asynchronous!
return ListenableFutureTask.create(new Callable<Graph>() {
public Graph call() {
return getGraphFromDatabase(key);
}
});
}
}
});
...其中“getAllGraphsFromDatabase()”执行聚合数据库查询而不是长度(键)单个查询。
LoadingCache的这两个组件如何一起播放?如果我对getAll()的请求中的某些键在缓存中不存在,那么它们将作为一个组加载loadAll(),但如果有些需要刷新,是否可以使用load()单独重新加载?如果是这样,是否有计划支持reloadAll()?
答案 0 :(得分:13)
以下是令人耳目一新的作品。
可以通过两种方式触发对缓存条目的刷新:
cache.refresh(key)
。refreshAfterWrite
,并且在写入后指定的时间后查询 。如果查询了符合重新加载条件的条目,则返回旧值,并触发(可能是异步)刷新。在刷新过程中,缓存将继续返回密钥的旧值。 (因此,如果getAll
请求中的某些键符合刷新条件,则会返回旧值,但这些键的值将(可能是异步)重新加载。)
CacheLoader.reload(key, oldValue)
的默认实现只返回Futures.immediateFuture(load(key))
,它(同步)重新计算该值。如果您希望进行缓存刷新,建议使用更复杂的异步实现。
我认为我们现在不倾向于提供reloadAll
。我怀疑它是可能的,但事情已经足够复杂了,而且我认为我们倾向于等到我们看到对这种事情的特定需求。