2017-01-16 14 views
3

私は、複数のスレッドからデータ構造にエントリを移入し、特定のサイズに達した後に古いレコードを削除したいというユースケースを持っています。そこで私はGuava Loading Cacheを使うことにしました。Loading Cache guavaにエントリを追加する方法は?

ロードキャッシュに複数のスレッドからエントリを取り込み、退去ベースのポリシーをSize Based Evictionと設定したいとします。

private final ScheduledExecutorService executorService = Executors 
     .newSingleThreadScheduledExecutor(); 
    private final LoadingCache<String, DataBuilder> cache = 
     CacheBuilder.newBuilder().maximumSize(10000000) 
      .removalListener(RemovalListeners.asynchronous(new CustomListener(), executorService)) 
      .build(new CacheLoader<String, DataBuilder>() { 
      @Override 
      public DataBuilder load(String key) throws Exception { 
       // what I should do here? 
       // return 
      } 
      }); 

// this will be called from multiple threads to populate the cache 
public void addToCache(String key, DataBuilder dataBuilder) { 
    // what I should do here? 
    //cache.get(key). 
} 

addToCache方法はcacheを移入するために、複数のスレッドから呼び出されます。私はキャッシュを埋めるためにaddToCacheメソッドの中で何をしなければならないのか混乱させています。また、私のloadメソッドはどのように見えますか?

ここでDataBuilderは私のビルダーパターンです。

+0

どのように我々はあなたがあなたのデータをロードする方法を知っている必要がありますか?そして、キャッシュを遅延ロードにするのではなく、なぜキャッシュを事前移入したいのですか? – shmosel

+0

私は 'addToCache'メソッドで' DataBuilder'を利用できるようになって以来、私の質問をしていました。 LoadingCacheにデータを挿入するにはどうしたらいいですか?それは私の混乱です。 –

答えて

7

明らかに問題は、あなたがCacheLoaderの主な目的を持っていないということです。

get(K key)getUnchecked(K key)を呼び出すときCacheLoaderは、我々はいくつかのスレッドを持っている場合でも、同じの値を取得しようとしているような方法で自動的に(まだキャッシュに存在しません)指定したキーの値をロードするために使用されますキーを同時に押すと、実際には1つのスレッドだけが値をロードし、すべての呼び出しスレッドは同じ値を持ちます。

これは通常、データベースへのアクセスや長い計算の結果など、読み込む値に時間がかかる場合に便利です。長い時間を要するのは、複数のスレッドが同時に同じ値をロードすると、すべての呼び出しスレッドのデータを1つのスレッドだけがロードするようなメカニズムがなくてもリソースを無駄にすることになります。

ここでは、DataBuilderのインスタンスを構築するのに時間がかかるか、またはすべてのスレッドが特定のキーに対して同じインスタンスを持つことを保証する必要があるとします。実際にはCacheLoaderが必要です。 :CacheLoader

new CacheLoader<String, DataBuilder>() { 
    @Override 
    public DataBuilder load(String key) throws Exception { 
     return callSomeMethodToBuildItFromTheKey(key); // could be new DataBuilder(key) 
    } 
} 

おかげで、あなたはあなたのキャッシュがcache.get(myKey)またはcache.getUnchecked(myKey)を呼び出すスレッドによってシーンの後ろに取り込まれますようもはや明示的putを呼び出す必要がありません。手動でキャッシュを移入する場合

は、あなたは単に次のように任意のCacheようput(K key, V value)メソッドを使用することができます:あなたはキャッシュを自分で移入する場合は、あなたがCacheLoaderを必要としない

public void addToCache(String key, DataBuilder dataBuilder) { 
    cache.put(key, dataBuilder); 
} 

Cacheインスタンスを構築するためにbuild(CacheLoader<? super K1,V1> loader)の代わりにbuild()と電話するだけで済みます(これはもうLoadingCacheにはなりません)。

あなたのコードは次のようになります。

private final Cache<String, DataBuilder> cache = 
     CacheBuilder.newBuilder().maximumSize(10000000) 
      .removalListener(
       RemovalListeners.asynchronous(new CustomListener(), executorService) 
     ).build(); 
+1

ありがとうございます。今私にははっきりしています。 –

+0

@NicolasFilotto私はまた、グアバのキャッシュ[ここ](http://stackoverflow.com/questions/41777172/how-to-empty-guava-cache-every-30-seconds-while-sending-it-to)に関する質問があります - 他の方法)。あなたが私を助けることができるかどうかを見たいと思った? – john

関連する問題