8

关于 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()?

4

1 回答 1

15

以下是令人耳目一新的工作原理。

刷新缓存条目可以通过两种方式触发:

  1. 明确地,与cache.refresh(key).
  2. 隐式地,如果配置了缓存,并且在写入后指定的时间量后查询refreshAfterWrite条目。

如果查询了符合重新加载条件的条目,则返回旧值,并触发(可能是异步的)刷新。在刷新过程中,缓存将继续返回键的旧值。(因此,如果请求中的某些键getAll符合刷新条件,它们的旧值将被返回,但这些键的值将(可能异步)重新加载。)

仅返回的默认实现,它(同步)重新计算值。如果您希望进行缓存刷新,建议使用更复杂的异步实现。CacheLoader.reload(key, oldValue)Futures.immediateFuture(load(key))

我认为我们目前不倾向于提供reloadAll。我怀疑这是可能的,但事情已经足够复杂了,我认为我们倾向于等到我们看到对这种东西的具体需求。

于 2012-04-14T17:08:20.057 回答