java并发编程实战-构建高效且可伸缩的结果缓存

构建高效且可伸缩的结果缓存
1,缓存在服务器应用程序中是一个非常重要的组件。
2,以下讲解一个高效且可伸缩的缓存示例

代码如下

public class CacheSample<IN, OUT> {
	/*
	 * 缓存类容器
	 * 1,选择线程安全的ConcurrentMap,它提供了并发读写的线程安全,以及“先检查再执行”这样的原子操作putIfAbsent
	 * 2,选择Future,避免直接存储计算结果值,导致高并发下多个线程同时计算同一个值的情况
	*/
	private final ConcurrentMap<IN, Future<OUT>> cache = new ConcurrentHashMap<IN, Future<OUT>>();
	
	public OUT doSomething(final IN arg) throws InterruptedException {
        while (true) {
            Future<OUT> f = cache.get(arg);
            if (f == null) {
            	// 如果没有IN对应的Future,则创建Future
                Callable<OUT> eval = new Callable<OUT>() {
                    public OUT call() throws InterruptedException {
                        return doing(arg);
                    }
                };
                FutureTask<OUT> ft = new FutureTask<OUT>(eval);
                // 通过putIfAbsent完成“先检查再添加”的原子操作
                // putIfAbsent如果已存在则返回已存在的值,如果不存在则添加新建的Future并返回null
                f = cache.putIfAbsent(arg, ft);
                if (f == null) {
                	// 如果新添加进缓存,则启动计算
                    f = ft;
                    ft.run();
                }
            }
            try {
            	// 不管f是新创建的还是通过缓存中获取的,如果Future还没计算结束就阻塞,如果计算结束就获取值
                return f.get();
            } catch (CancellationException e) {
            	// 当某个计算被取消或者失败,需要从缓存中移除该IN及对应的Future
            	// 否则,将持续性获取不到正确的值,但同时又无法再进行新的计算(缓存污染)
                cache.remove(arg, f);
            } catch (ExecutionException e) {
                throw LaunderThrowable.launderThrowable(e.getCause());
            }
        }
    }
	
	private OUT doing(final IN arg){
		// 非常耗时的处理过程................
		return null;
	}
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值