技术头条 - 一个快速在微博传播文章的方式     搜索本站
您现在的位置首页 --> 算法 --> 学习:一个并发的Cache

学习:一个并发的Cache

浏览:4987次  出处信息
以下是代码片段:
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. (为什么? 这相当于放一个Latch)
3) 使用了FutureTask来调度计算, 这样多个线程可以分别进行针对不同的参数的计算
4) 基于FutureTask的特性, 先把FutureTask放进了cache, 再对FutureTask计算
5) 用了一个 while(true) 无限循环…
(为什么? 因为如果发现已经有一个线程中进行相同的计算的话, 就直接等待计算结果. 但是等待过程中, 如果FutureTask被中断了呢? 抓住异常, 再等…)
6) 使用putIfAbsent操作, 避免出现两个线程都进行相同的计算

建议继续学习:

  1. 一种常见的并发编程场景的处理    (阅读:22618)
  2. Rolling cURL: PHP并发最佳实践    (阅读:10343)
  3. 查看 Apache并发请求数及其TCP连接状态    (阅读:8481)
  4. 大型高并发高负载网站的系统架构分析    (阅读:7729)
  5. 大并发下的高性能编程 – 改进的(用户态)自旋锁    (阅读:7165)
  6. Buffer和cache的区别是什么?    (阅读:6838)
  7. 并发编程系列之一:锁的意义    (阅读:5906)
  8. 谈冷热数据    (阅读:5758)
  9. Linux操作系统中内存buffer和cache的区别    (阅读:5316)
  10. 并发框架Disruptor译文    (阅读:5113)
QQ技术交流群:445447336,欢迎加入!
扫一扫订阅我的微信号:IT技术博客大学习
© 2009 - 2024 by blogread.cn 微博:@IT技术博客大学习

京ICP备15002552号-1