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()」は、length(keys)の個々のクエリではなく、集約データベースクエリを実行します。

LoadingCacheのこれら2つのコンポーネントはどのように連携しますか?getAll()へのリクエストの一部のキーがキャッシュに存在しない場合、それらはloadAll()を使用してグループとしてロードされますが、更新が必要な場合、それらはload()を使用して個別に再ロードされますか?もしそうなら、reloadAll()をサポートする計画はありますか?

4

1 に答える 1

15

さわやかな仕組みは次のとおりです。

キャッシュエントリの更新は、次の2つの方法でトリガーできます。

  1. 明示的に、cache.refresh(key)
  2. 暗黙的に、キャッシュがで構成されていて、エントリが書き込まれてから指定された時間が経過した後にrefreshAfterWriteエントリがクエリされた場合。

リロードの対象となるエントリが照会されると、古い値が返され、(場合によっては非同期の)更新がトリガーされます。更新の進行中、キャッシュはキーの古い値を返し続けます。(したがって、getAllリクエスト内の一部のキーが更新の対象である場合、それらの古い値が返されますが、それらのキーの値は(おそらく非同期で)再ロードされます。)

デフォルトの実装は、値を(同期して)再計算するCacheLoader.reload(key, oldValue)だけを返します。Futures.immediateFuture(load(key))キャッシュの更新を行う予定の場合は、より高度な非同期実装をお勧めします。

reloadAll現時点では提供する傾向はないと思います。可能だと思いますが、それなりに複雑で、具体的な需要が出るまで待つ傾向があると思います。

于 2012-04-14T17:08:20.057 に答える