当前位置: 首页 > article >正文

高效缓存设计的哲学

文章目录

    • 引言
    • 基于缓存存储运算结果
    • 锁分段散列减小锁粒度
    • 异步化提升处理效率
    • 原子化避免重复运算
    • 小结
    • 参考

引言

基于缓存存储运算结果

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

 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操作:

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避免计算的阻塞,当然因为判空和创建任务非原子操作,很可能还是出现重复计算的情况:

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;}

原子化避免重复运算

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

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();}

小结

参考

http://www.lryc.cn/news/2383677.html

相关文章:

  • 【生态信息】开源软件全方位解析
  • FastAPI在 Nginx 和 Docker 环境中的部署
  • 计算机网络相关面试题
  • 根据当前日期计算并选取上一个月和上一个季度的日期范围,用于日期控件的快捷选取功能
  • 【C++】set、map 容器的使用
  • 【MySQL】第1节|全面理解MySQL架构
  • YOLOv8模型剪枝笔记(DepGraph和Network Slimming网络瘦身)
  • App Builder技术选型指南:从AI编程到小程序容器,外卖App开发实战
  • TDengine 高可用——三副本
  • el-table高度自适应、数据查询后高度展示错误问题
  • 【蓝桥杯真题精讲】第 16 届 Python A 组(省赛)
  • Java接口设计:ECharts热力图的绘制
  • 深入理解 MongoDB 的 _id 和 ObjectId:从原理到实践
  • C++内存复制
  • 【notepad++如何设置成中文界面呢?】
  • 当AI遇上科研:北大“科学导航”重塑学术探索全流程
  • 大模型在闭合性胫骨平台骨折诊疗全流程中的应用研究报告
  • PHP学习笔记(八)
  • C#中WSDL文件引用问题
  • Ubuntu 22.04上升级Node.js版本
  • 养生新策:五维开启健康生活
  • 生成对抗网络(GAN)原理
  • 【SpringBoot实战指南】使用 Spring Cache
  • centos8 配置网桥,并禁止kvm默认网桥
  • C++:list容器,deque容器
  • 【Node.js】全栈开发实践
  • 自定义类型-联合体
  • Qt项目开发中所遇
  • ubuntu sh安装包的安装方式
  • Redis语法大全