---
title: スケーラブルなリザルトキャッシュの作り方
tags: []
categories: ["Programming", "Java", "java", "util", "concurrent"]
date: 2010-01-03T12:18:20Z
updated: 2010-01-03T12:22:21Z
---

「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`なところがポイント。
