学習:同時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つのスレッドが同じ計算を行うことを避ける