2

値をキャッシュしようとしていintます (DB から何かを数えます)。このカウントにはかなりの時間がかかる可能性があるため、最初に 200 ミリ秒のタイムアウトで試してみたいと思います。しかし、それが失敗した場合、2 つのシナリオがあります。

  1. Mycacheが入力され、現在の値を返し、非同期で再入力します。
  2. cache入力されていません。入力してブロックし、値を返します。

私は「キャッシュ」と言っていますが、それは実際には単なるint値です。ここで本格的な機能cacheが必要かどうかはわかりません。Guava のSupplierを使用してみましたが、特定のユース ケースを統合する方法が見つかりません。

多くのスレッドがこの手順全体に入る可能性があることに注意してください。キャッシュが読み込まれない場合に備えて、最初のスレッドだけを待機させたいと思います。残りは待機せずに、キャッシュされた値をすぐに取得する必要があります。他のスレッドがキャッシュの再設定を完了した場合は、更新された値です。

これが私が今持っているもののサンプルコードです:

public class CountRetriever {

private Supplier<Integer> cache = Suppliers.memoize(countSupplier());

private Supplier<Integer> countSupplier() {
    return new Supplier<Integer>() {
        @Override
        public Integer get() {
            // Do heavy count from the DB
        }
    };
}

public int getCount() {
    try {
        return submitAsyncFetch();
    } catch (Exception e) {
        // It takes too long, let's use the cache
        return cache.get();
    }
}

private Integer submitAsyncFetch() {
    return executor.submit(new Callable<Integer>() {
        @Override
        public Integer call() throws Exception {
            // Do heavy count from the DB
        }
    }).get(200, TimeUnit.MILLISECONDS);
}
}
4

1 に答える 1

0

このようなことを試しましたか?

private int Map<String,Integer> cache = new HashMap<String,Integer>();

public getValue(String key){
  synchronized(cache){
    Integer value = cache.get(key);
    if(value == null) { 
       value = getValue();
       cache.put(key,value);
    }
    return value;
  }
}

もちろん、キャッシュにデータが入力されているときに2番目のスレッドが入ってくると、待機する必要があります。また、このソリューションでは、一度に1つのスレッドのみが値を読み取ることができるため、重要なブロックがいかに単純であるかを考えると、パフォーマンスに大きな影響を与えるとは思えませんが、同期ブロックをReadWriteLockに置き換えることをお勧めします。

于 2013-02-12T09:44:58.163 に答える