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

高效缓存设计的哲学

文章目录

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

引言

基于缓存存储运算结果

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

 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.dtcms.com/a/205594.html

相关文章:

  • 2025年- H42-Lc150 --146. LRU缓存(哈希表,双链表)需二刷--Java版
  • 网络图片的缓存和压缩
  • Rust 学习笔记:关于生命周期的练习题
  • 深度解析:Spark、Hive 与 Presto 的融合应用之道
  • uni-app学习笔记八-vue3条件渲染
  • 黑马+点评常见问题
  • work-platform阅读
  • OceanBase 开发者大会,拥抱 Data*AI 战略,构建 AI 数据底座
  • git checkout HEAD
  • 计及可再生能源不确定性的经济优化调度方法
  • Centos8安装 python3并保留系统的python2
  • I.MX6U Mini开发板通过GPIO口测试光敏传感器
  • 使用 OpenCV 实现哈哈镜效果
  • GPU P-State 模式说明
  • 红蓝对抗中的网络安全设备操作手册
  • 提问的艺术
  • Linux内存分页管理详解
  • SAR ADC 是选择先置位再比较,还是先比较再置位
  • 禁止window安全中心乱删文件
  • java 代码查重(三)常见的距离算法和相似度(相关系数)计算方法
  • 基于双通道频谱分析的振动信号故障诊断3
  • 从0开始学linux韦东山教程第四章问题小结(2)
  • Java虚拟机 -虚拟机栈
  • GUI实验
  • 漏洞修复的两种核心方法
  • day25- 系统编程之 标准IO(II) 及 文件IO
  • MCP-1:MCP组件与工作流程
  • 【leetcode】75.颜色分类
  • 一命通关单调栈
  • Vue.js教学第九章:Vue动态与异步组件,高效开发全攻略