java建立高效、可伸缩性缓存

缓存
写入前,先排重,同时要防止重复写(两个线程同时写入),或者是重复读(已有线程写入,正在计算,另一个线程可以不必继续访问,直接等待结果就好)。

关键点:
1- ConcurrentHashMap分段锁。
2- Callable启动线程,返回Future对象。

代码:


public interface Computable<K,V> {

    V compute(K arg)throws InterruptedException;

}


public class Memoizer<K,V> implements Computable<K,V> {

    private final Map<K,Future<V>> cache = new ConcurrentHashMap<>();
    private  Computable<K,V> c=null;

    public Memoizer(Computable<K,V> c) { this.c = c; }

    public V compute(final K arg) throws InterruptedException{

        while(true){
            Future<V> f = cache.get(arg);
            if(f==null){
                Callable<V> call = new Callable<V>() {
                    @Override
                    public V call() throws InterruptedException {
                        return c.compute(arg);
                    }
                };
                FutureTask<V> ft = new FutureTask<V>(call);
                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){
                e.printStackTrace();
            }
        }

    }
}

分析:
在多线程情况下,建立高效缓存,首先要考虑的是缓存的重复写,和重复读问题。
如何解决重复写
1:利用ConcurrentHashMap解决重复写,相同的key覆盖,同时分段锁segment更加精细,有利于数据的同步。
2:在写入前检查是否已有线程写入cache.get(arg)。
3:没有写入再通过ConcurrentHashMap的cache.putIfAbsent(arg,ft)方法,提供原子性写入(防止两个线程同时写入的情况。)
4:如果写入了,则直接等待正在进行计算,f.get()处于阻塞状态,直到返回结果。

说明
受教与《并发编程实践》

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值