码迷,mamicode.com
首页 > 其他好文 > 详细

缓存实现思路

时间:2018-08-12 18:50:17      阅读:194      评论:0      收藏:0      [点我收藏+]

标签:实现   阻塞   判断   tst   this   产生   情况下   map   compute   

缓存主要为了解决各个组件之间读取速度不匹配问题,比如寄存器是L1的缓存,L1是L2的缓存,L2是L3的缓存,L3是内存的缓存等。通过读Java Concurrency Practice P85,实现了一个简单可以添加和获取数据的缓存。其它的诸如缓存过期,更新缓存等没有实现- -!!

代码

计算接口,用到了装饰者模式。


public interface Computable<A,V> {
    V compute(A arg);
}

一种计算的实现

public class ExpensiveFunction implements Computable<String,BigInteger> {

    @Override
    public BigInteger compute(String arg) {
       // 经过长时间计算后
        try {
            Thread.sleep(500000);           
        } catch (InterruptedException ie) {

        }
        return new BigInteger(arg); 
    }

}

版本1

通过HashMap时间复杂度为O(1)的特性以及synchronized保证线程安全来构建缓存


public class MyCacheV1<A,V> implements Computable<A,V>{

    private Map<A,V> cache = new HashMap<>();
    private Computable computable;

    public MyCacheV1(Computable computable) {
        this.computable = computable;
    }

    @Override
    public synchronized V compute(A arg) {
        V result = cache.get(arg);
        if (result == null) {
            result = (V)computable.compute(arg);
            cache.put(arg,result);
        }
        return result;
    }

}

版本2

版本1添加了synchronized,多线程情况下造成性能下降 -> 换成ConcurrentHashMap

public class MyCacheV2<A,V> implements Computable<A,V>{

    private Map<A,V> cache = new ConcurrentHashMap<>();
    private Computable computable;

    public MyCacheV2(Computable computable) {
        this.computable = computable;
    }

    @Override
    public V compute(A arg) {
        V result = cache.get(arg);
        if (result == null) {
            result = (V)computable.compute(arg);
            cache.put(arg,result);
        }
        return result;
    }

}

版本3

版本2先判断 -> 在计算属于复合操作而且没有加锁导致线程不安全会产生重读计算。如果遇到计算时间非常长的计算,一旦重复会消耗大量的资源。
解决思路:如果其他线程正在计算目标值,当前线程阻塞直到其它线程计算出结果返回即可。
实现:通过FutureTask的get()方法。如果没有结果,会阻塞当前线程。

public class MyCacheV3<A,V> implements Computable<A,V>{

    private Map<A,FutureTask> cache = new ConcurrentHashMap<>();
    private Computable computable;

    public MyCacheV3(Computable computable) {
        this.computable = computable;
    }

    @Override
    public V compute(A arg) {
        Future future = cache.get(arg);
        if (future == null) {
            FutureTask futureTask = new FutureTask(new Callable() {
                @Override
                public V call() throws Exception {
                    return (V)computable.compute(arg);
                }
            });
            // 用到了ConcurrentHashMap的原子操作
            future = cache.putIfAbsent(arg,futureTask);
            // 二次判断
            if (future == null) {future = futureTask; futureTask.run();}
        }
        V result = null;
        try {
            result = (V) future.get();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
        return result;
    }

}

缓存实现思路

标签:实现   阻塞   判断   tst   this   产生   情况下   map   compute   

原文地址:https://www.cnblogs.com/jinshuai86/p/9463611.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!