高效缓存设计的哲学

文章目录

引言

基于缓存存储运算结果

利用缓存避免非必要的计算,提升结果获取速度,但还是存在问题,每个线程都需要等待锁才能看结果和运算:

java 复制代码
 public final Map<Integer, Integer> cache = new HashMap<>();


    public synchronized int compute(int arg) {

        if (cache.containsKey(arg)) {//若存在直接返回结果
            return cache.get(arg);
        } else {//若不存在则计算并返回
            int result = doCompute(arg);
            cache.put(arg, result);
            return result;
        }
    }

    private int doCompute(int key) {
        ThreadUtil.sleep(500);
        return key << 1;
    }

锁分段散列减小锁粒度

利用分段锁分散压力,但是运算耗时可能导致重复计算和put操作:

java 复制代码
public final Map<Integer, Integer> cache = new ConcurrentHashMap<>();


    public int compute(int arg) {
        Integer res = cache.get(arg);
        if (res == null) {
            int result = doCpmpute(arg);
            cache.put(arg, result);
        }
        return res;
    }

    private int doCpmpute(int arg) {
        ThreadUtil.sleep(3000);
        return arg << 1;
    }

异步化提升处理效率

使用future避免计算的阻塞,当然因为判空和创建任务非原子操作,很可能还是出现重复计算的情况:

java 复制代码
public final Map<Integer, FutureTask<Integer>> cache = new ConcurrentHashMap<>();


    public int compute(int key) throws ExecutionException, InterruptedException {
        FutureTask<Integer> f = cache.get(key);
        if (f == null) {
            FutureTask<Integer> futureTask = new FutureTask<>(() -> doCompute(key));
            //缓存保证下一个线程看到时直接取出使用
            cache.put(key, futureTask);
            futureTask.run();
            f=futureTask ;
        }
        return f.get();
    }

    private int doCompute(int arg) {
        ThreadUtil.sleep(3000);
        return arg << 1;
    }

原子化避免重复运算

原子操作避免重复计算,并发运算一个数字时都采用同一个任务的结果

java 复制代码
public int compute(int key) throws ExecutionException, InterruptedException {
        FutureTask<Integer> f = cache.get(key);
        if (f == null) {
            FutureTask<Integer> futureTask = new FutureTask<>(() -> doCompute(key));
            //原子操作添加,若返回空说明第一次添加,则让这个任务启动,其他线程直接基于缓存中的任务获取结果
            f = cache.putIfAbsent(key, futureTask);
            if (f == null) {
                f = futureTask;
                f.run();
            }
            futureTask.run();
            f = futureTask;
        }
        return f.get();
    }

小结

参考

相关推荐
码匠许师傅1 小时前
【设计模式精讲】7.建造者模式(Builder)
设计模式·建造者模式
码匠许师傅2 小时前
【设计模式精讲】6.抽象工厂(Abstract Factory)
c++·设计模式
workflower16 小时前
人形机器人灵巧手产业链
人工智能·设计模式·机器人·云计算·无人机
Java后端的Ai之路18 小时前
03、Python - 抽象工厂模式
开发语言·python·设计模式·抽象工厂模式·通用智慧
AI人工智能+电脑小能手1 天前
大白话说Java设计模式-45-解释器模式(源码剖析篇)
java·设计模式·解释器模式·源码分析·pattern·spel·javacc
码匠许师傅1 天前
【设计模式精讲】4.单例模式(Singleton)
c++·单例模式·设计模式
雾削木1 天前
2026 编程领域热点知识速览:AI 辅助开发、设计模式实战与嵌入式高效迭代
人工智能·设计模式
AI人工智能+电脑小能手2 天前
大白话说Java设计模式-42-访问者模式(业务实战篇)
java·spring·设计模式·访问者模式·asm·营销规则·数据结构与操作分离
AI人工智能+电脑小能手2 天前
大白话说Java设计模式-43-访问者模式(源码剖析篇)
java·设计模式·访问者模式·源码分析·elementvisitor·asm classvisitor·spring spel
Michael_lcf3 天前
Agent设计模式:思考-行动-观察循环的本质与局限
设计模式·agent设计模式·agent设计模式的本质