学習:同時Cache


public class Memoizer implements Computable {
    private final ConcurrentMap> cache
        = new ConcurrentHashMap>();
    private final Computable c;

    public Memoizer(Computable c) { this.c = c; }

    public V compute(final A arg) throws InterruptedException {
        while (true) {
            Future f = cache.get(arg);
            if (f == null) {
                Callable eval = new Callable() {
                    public V call() throws InterruptedException {
                        return c.compute(arg);
                    }
                };
                FutureTask ft = new FutureTask(eval);
                f = cache.putIfAbsent(arg, ft); //  FutureTask     
                if (f == null) { f = ft; ft.run(); } //    
            }
            try {
                return f.get();
            } catch (CancellationException e) {
                cache.remove(arg, f);
            } catch (ExecutionException e) {
                throw launderThrowable(e.getCause());
            }
        }
    }
}
 
このCacheのデザインはとても面白くて、多くの合併の要素を考慮しました.Cacheは簡単なMap方式で実現する.
1)ConcurrentHashMapを用いて計算結果を格納2)最も興味深い点は,ConcurrentHashMapに格納されている内容がFutureTaskである.(なぜですか?これは1つのLatchに相当します)3)FutureTaskを使用して計算をスケジューリングすることで、複数のスレッドがそれぞれ異なるパラメータに対する計算を行うことができます4)FutureTaskの特性に基づいて、まずFutureTaskをcacheに入れて、さらにFutureTask計算5)にwhile(true)無限ループを1つ使いました…(なぜですか?すでに1つのスレッドで同じ計算が行われていることが判明したら、計算結果をそのまま待つことになります.しかし、待ちの過程でFutureTaskが中断されたら?異常を捉え、さらに...)6)putIfAbsent操作を使い、2つのスレッドが同じ計算を行うことを避ける