Google Guava的CacheLoader loadAll()vs reload()语义

spi*_*tor 7 java caching guava

我真正喜欢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);
               }
             });
           }
         }
       });
Run Code Online (Sandbox Code Playgroud)

...其中"getAllGraphsFromDatabase()"执行聚合数据库查询而不是长度(键)单个查询.

如何将LoadingCache的这两个组件一起播放?如果我对getAll()的请求中的某些键在缓存中不存在,那么它们将作为一个组加载loadAll(),但如果有些需要刷新,是否可以使用load()单独重新加载?如果是这样,是否有计划支持reloadAll()?

Lou*_*man 13

这是令人耳目一新的工作方式.

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

  1. 显然,有cache.refresh(key).
  2. 隐式地,如果配置了缓存,则在写入后的指定时间后查询refreshAfterWrite条目.

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

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

我不认为我们现在倾向于提供reloadAll.我怀疑这是可能的,但事情已经足够复杂了,而且我认为我们倾向于等到我们看到对这种事情的特定需求.

  • 当你实现`reload`时,在具有固定数量线程的`ListeningExecutorService`上创建返回的`ListenableFuture`.这将限制并发执行查询的数量. (2认同)