构建高效且可伸缩的结果缓存

  • 使用ConcurrentMap而不使用HashMap可以提高并发性,即避免下面问题:

    • 使用HashMap需要对整个compute加锁,synchronized


      构建高效且可伸缩的结果缓存_第1张图片
      并发性降低
  • 缓存Map中存放Future而不使用最终的结果,可以避免同一个key被计算多次情况。如下:

构建高效且可伸缩的结果缓存_第2张图片
相同值计算两次
  • 使用ConcurrentMap接口的putIfAbsent方法(“先检查再执行”的原子性操作)而不是put,可以避免重复计算问题,如下:
构建高效且可伸缩的结果缓存_第3张图片
相同值计算2次
package net.jcip.examples;
import java.util.concurrent.*;
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);
                if (f == null) {
                    f = ft;
                    ft.run();  //将会调用c.compute(arg)
                }
            }
            try {
                return f.get();
            } catch (CancellationException e) {
                cache.remove(arg, f);
            } catch (ExecutionException e) {
                throw LaunderThrowable.launderThrowable(e.getCause());
            }
        }
    }
}

你可能感兴趣的:(构建高效且可伸缩的结果缓存)