IK.AM

@making's tech note


スケーラブルなリザルトキャッシュの作り方

🗃 {Programming/Java/java/util/concurrent}
🗓 Updated at 2010-01-03T12:18:20Z  🗓 Created at 2010-01-03T12:18:20Z   🌎 English Page

「Java並行処理プログラミング」の写経ですが、とても興味深い内容だったのでメモ。

public class Memoizer<A, V> implements Computable<A, V> {
  private final ConcurrentMap<A, Future<V>> cache = new ConcurrentHashMap<A, Future<V>>();
  private final computable<A, V> c;
  
  public V compute(final A arg) throws InterruptedException {
    while (true) {
      Future<V> f = cache.get(arg);
      if (f == null) {
        Callable<V> eval = new Callable<V> {
          public V call() throws InterruptedException {
            return c.compute(arg);
          }
        };
        FutureTask<V> ft = new FutureTask<V>(eval);
        f = cache.putIfAbsent(arg, ft);
        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());
      }
    }
  }
}

putIfAbsentはおまけで、ConcurrentHashMapのvalueがFutureなところがポイント。


✒️️ Edit  ⏰ History  🗑 Delete