【设计一个缓存--针对各种类型的缓存】

news2025/1/23 4:50:14

设计一个缓存--针对各种类型的缓存

  • 1. 设计顶层接口
  • 2. 设计抽象类 -- AbstractCacheManager
  • 3. 具体子类
    • 3.1 -- AlertRuleItemExpCacheManager
    • 3.2 -- AlertRuleItemSrcCacheManager
  • 4. 类图关系

1. 设计顶层接口

// 定义为一个泛型接口,提供给抽象类使用
public interface CacheManager<T> {
	// 获取所有的缓存item
    List<T> getAll();
	// 根据条件获取某些缓存item
    List<T> get(Predicate<T> predicate);
	// 设置缓存
    boolean set(T t);
	// 设置缓存list
    boolean set(List<T> tList);
}

有接口必定有实现类或者抽象类,实现接口。
那为了更好地控制子类的行为,可以做一个抽象类,控制子类行为。

  • 分析:
    • 抽象类作为缓存管理的话,那么就需要提供安全访问数据
    • 需要考虑线程安全问题。
    • 花絮: 不仅要满足上述需求,而且让代码尽量简洁。

2. 设计抽象类 – AbstractCacheManager

  • 属性设计:
    • 需要一个缓存
    • 需要一个线程安全机制方案
  • 行为设计:
    • 自己的行为:
      • 利用线程安全机制控制缓存的读写。
      • 权限:仅自己可访问
    • 后代的行为:
      • 访问一些简单api方法即可实现安全访问缓存
      • 权限:公共访问
  • 设计模式:
    • 包裹思想,将后代行为方法中,包裹一层安全访问的行为。

Java Code:

 // properties design:
protected ConcurrentMap<String, T> cache;

private ReentrantReadWriteLock lock = new ReentrantReadWriteLock();

// subclass to implements these abstract methods.

protected abstract List<T> getAllByCache();

protected abstract void setByCache(T t);

protected abstract void setByCache(List<T> tList);

protected abstract List<T> getByCache(Predicate<T> predicate);

// next content needs to consider safety of multithreads. following methods do implements.
// entry to use
@Override
public final List<T> getAll() {
   return this.readLockThenGet(() -> this.getAllByCache());
}

@Override
public final List<T> get(Predicate<T> predicate) {
   return this.readLockThenGet(pre -> getByCache(pre), predicate);
}

@Override
public final boolean set(T t) {
   return this.writeLockThenSet((Consumer<T>) obj -> set(obj), t);
}

@Override
public final boolean set(List<T> tList) {
   return this.writeLockThenSet((Consumer<List<T>>) list -> set(list), tList);
}

// current abstract class access cache object.
private boolean writeLockThenSet(Consumer consumer, Object object){
    boolean wLock = false;
    try {
        if (!(wLock = lock.writeLock().tryLock(100, TimeUnit.MICROSECONDS))) {
            return false;
        }
        consumer.accept(object);
        return true;
    } catch (Exception e) {
        return false;
    } finally {
        if(wLock) {
            lock.writeLock().unlock();
        }
    }
}

private List<T> readLockThenGet(Supplier<List<T>> supplier){
    boolean rLock = false;
    try{
        if(!(rLock = lock.readLock().tryLock(100, TimeUnit.MICROSECONDS))){
            return null;
        }
        return supplier.get();
    }catch (Exception e){
        return null;
    }finally {
        if(rLock) {
            lock.readLock().unlock();
        }
    }
}

private List<T> readLockThenGet(Function<Predicate<T>, List<T>> function, Predicate<T> predicate){
    boolean rLock = false;
    try{
        if(!(rLock = lock.readLock().tryLock(100, TimeUnit.MICROSECONDS))){
            return null;
        }
        return function.apply(predicate);
    }catch (Exception e){
        return null;
    }finally {
        if(rLock) {
            lock.readLock().unlock();
        }
    }
}

3. 具体子类

3.1 – AlertRuleItemExpCacheManager

@Component("alertRuleItemExpCacheManager")
public class AlertRuleItemExpCacheManager<T extends AlertRuleItemExpCache> extends AbstractCacheManager<AlertRuleItemExpCache> {
   @Resource
   private AlertRuleItemExpDao alertRuleItemExpDao;

   @Override
   protected List<AlertRuleItemExpCache> getAllByCache() {
       if (null == cache) {
           List<AlertRuleItemExp> alertRuleItemSrcList =
                   alertRuleItemExpDao.selectList(Wrappers.<AlertRuleItemExp>lambdaQuery().eq(AlertRuleItemExp::getDeleted, 0));
           cache = alertRuleItemSrcList.stream().map(entity -> entity.toCache())
                   .collect(Collectors.toConcurrentMap(cache -> cache.getId().toString(), cache -> cache));
       }
       return cache.values().stream()
               .sorted(Comparator.comparing(AlertRuleItemExpCache::getId))
               .collect(Collectors.toList());
   }

   @Override
   protected void setByCache(AlertRuleItemExpCache alertRuleItemExpCache) {
       cache.put(alertRuleItemExpCache.getId().toString(), alertRuleItemExpCache);
   }

   @Override
   protected void setByCache(List<AlertRuleItemExpCache> alertRuleItemExpCacheList) {
       alertRuleItemExpCacheList.parallelStream().forEach(alertRuleItemExpCache ->
               cache.put(alertRuleItemExpCache.getId().toString(), alertRuleItemExpCache));
   }

   @Override
   protected List<AlertRuleItemExpCache> getByCache(Predicate<AlertRuleItemExpCache> predicate) {
       return getAllByCache().stream().filter(cache -> predicate.test(cache)).collect(Collectors.toList());
   }
}

3.2 – AlertRuleItemSrcCacheManager

@Component("alertRuleItemSrcCacheManager")
public class AlertRuleItemSrcCacheManager<T extends AlertRuleItemSrcCache> extends AbstractCacheManager<AlertRuleItemSrcCache> {
   @Resource
   private AlertRuleItemSrcDao alertRuleItemSrcDao;

   @Override
   protected List<AlertRuleItemSrcCache> getAllByCache() {
       if (null == cache) {
           List<AlertRuleItemSrc> alertRuleItemSrcList =
                   alertRuleItemSrcDao.selectList(Wrappers.<AlertRuleItemSrc>lambdaQuery().eq(AlertRuleItemSrc::getDeleted, 0));
           cache = alertRuleItemSrcList.stream().map(entity -> entity.toCache())
                   .collect(Collectors.toConcurrentMap(cache -> cache.getId().toString(), cache -> cache));
       }
       return cache.values().stream()
               .sorted(Comparator.comparing(AlertRuleItemSrcCache::getId))
               .collect(Collectors.toList());
   }

   @Override
   protected void setByCache(AlertRuleItemSrcCache alertRuleItemSrcCache) {
       cache.put(alertRuleItemSrcCache.getId().toString(), alertRuleItemSrcCache);
   }

   @Override
   protected void setByCache(List<AlertRuleItemSrcCache> alertRuleItemSrcCacheList) {
       alertRuleItemSrcCacheList.parallelStream().forEach(alertRuleItemSrcCache ->
               cache.put(alertRuleItemSrcCache.getId().toString(), alertRuleItemSrcCache));
   }

   @Override
   protected List<AlertRuleItemSrcCache> getByCache(Predicate<AlertRuleItemSrcCache> predicate) {
       return getAllByCache().stream().filter(cache -> predicate.test(cache)).collect(Collectors.toList());
   }
}

4. 类图关系

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1214694.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Linux命令(123)之mail

linux命令之mail 1.mail介绍 linux命令mail是用来发送邮件 2.mail用法 mail -s "Subject" EmailAddress < EmailMessage 参数说明-s指定邮件主题SubjectEmailAddress指定邮件地址EmailMessage指定邮件内容3.实例 3.1.配置QQ邮件发送 1.安装sendmail/mailx …

ThreadLocal这点牛角尖总算是给我钻明白了

前言 这个问题算是我的一个羞耻点&#xff0c;起源于一次面试中&#xff0c;面试官问ThreadLocal的底层实现是啥&#xff0c;我那时候一直以为ThreadLocal是一个类似于Redis一样的独立于线程外的第三方存储容器&#xff0c;如何底层维护了一个Map结构&#xff0c;以线程ID为Key…

iOS性能优化

了解屏幕成像的原理。 有一个电子枪然后在很多横轴方向上 发射电子&#xff0c;不同横轴的电子枪根据显示器中的硬件时钟产生一系列的定时信号&#xff0c;以此来让电子以不同的时间发射出去 这些电子一瞬间的运动形成了一帧动画。 CPU优化&#xff1a; 1.文本计算优化 如果一…

DSVPN简介

定义 动态智能VPN&#xff08;Dynamic Smart Virtual Private Network&#xff09;&#xff0c;简称DSVPN&#xff0c;是一种在Hub-Spoke组网方式下为公网地址动态变化的分支之间建立VPN隧道的解决方案。 目的 越来越多的企业希望建立Hub-Spoke方式的IPSec VPN网络将企业总部…

2760. 最长奇偶子数组 : 抽丝剥茧,图解双指针做法正确性

题目描述 这是 LeetCode 上的 「2698. 求一个整数的惩罚数」 &#xff0c;难度为 「简单」。 Tag : 「双指针」、「滑动窗口」 给你一个下标从 开始的整数数组 nums 和一个整数 threshold。 请你从 nums 的子数组中找出以下标 l 开头、下标 r 结尾 ( ) 且满足以下条件的 最长子…

控制器宕机之SBC相关

简介: 本文主要以FS6500系列展开介绍&#xff0c;介绍深度安全故障(深度睡眠)状态的转换&#xff0c;以及相关寄存器值的变化过程 1.控制器什么时候会因为SBC停止工作? 窗口看门狗未及时喂狗达到故障计数最大值芯片进入某种(deep fail state)模式或LP-DFS模式或LP-Sleep模式…

阿里云的99元服务器和腾讯云的88元云服务器选择哪个?怎么选?

近日&#xff0c;阿里云宣布在2023年双十一优惠活动中推出了一系列降价措施&#xff0c;使得同配置的云服务器比腾讯云更具竞争力。这一消息不仅在云计算领域引起了轰动&#xff0c;更为广大互联网用户提供了更为实惠的选择。 阿里云推出99元一年的服务器&#xff0c;续费价格…

FreeSWITCH案例跟踪之一,sip bye发不出去

报故障的说&#xff0c;网关呼叫fs&#xff0c;网关收不到fs的sip bye Wireshark看call-flow, 是这样的&#xff1a; INVITE里面的contact是<sip:172.23.4.109:5060;transporttcp> 于是Wireshark设置过滤条件为ip.addr 172.23.4.109 and tcp.port 5060 fs tcp连网关被…

基于 HTTP Digest 与 CURL 以及 Requests 的兼容性问题:解决方案与推测原因

在使用Python库requests进行HTTP Digest认证时&#xff0c;我遇到了一个问题。当我使用requests.get()函数时&#xff0c;返回了401 Unauthorized错误&#xff0c;但是当我使用cURL命令时&#xff0c;认证成功。 解决方案&#xff1a; 确认使用的requests版本&#xff1a;我首…

大数据可视化Echarts基础快速入门

目录 一、什么是Ehcarts&#xff1f; 二、如何使用Echarts &#xff08;1&#xff09;引入Echarts的js文件 &#xff08;2&#xff09;查看文档&#xff0c;根据文档编写代码 一、什么是Ehcarts&#xff1f; 首先我们要知道什么数据可视化。什么是数据可视化&#xff1f;…

⑩【MySQL】存储引擎详解, InnoDB、MyISAM、Memory。

个人简介&#xff1a;Java领域新星创作者&#xff1b;阿里云技术博主、星级博主、专家博主&#xff1b;正在Java学习的路上摸爬滚打&#xff0c;记录学习的过程~ 个人主页&#xff1a;.29.的博客 学习社区&#xff1a;进去逛一逛~ 存储引擎 ⑩【MySQL存储引擎】1. MySQL体系结构…

大模型会毁了初级程序员 —— 对话图灵奖得主 Joseph Sifakis | 新程序员

【编者按】GPT 系列的面世影响了全世界、各个行业&#xff0c;对于开发者们的感受则最为深切。以 ChatGPT、Github Copilot 为首&#xff0c;各类 AI 编程助手层出不穷。编程范式正在发生前所未有的变化&#xff0c;从汇编到 Java 等高级语言&#xff0c;再到今天以自然语言为特…

main.js 中的 render函数

按照之前的单组件文件中的写法&#xff0c;我们的写法应该是这样的 import App from ./App.vuenew Vue({el: #app,templete: <App></App>,components: {App}, }) 1、定义el根节点。2、注册App组件。3、渲染 templete 模板 但是在脚手架工程中&#xff0c;他是这…

C++实现高频设计模式

面试能说出这几种常用的设计模式即可 1.策略模式 1.1 业务场景 大数据系统把文件推送过来&#xff0c;根据不同类型采取不同的解析方式。多数的小伙伴就会写出以下的代码&#xff1a; if(type"A"){//按照A格式解析 }else if(type"B"){//按照B格式解析 …

2023最受推荐的五款项目管理工具

1、进度猫 进度猫是国内一款轻量级项目管理工具&#xff0c;适用于实时协作的团队。 以甘特图为向导&#xff0c;基于任务清单todolist&#xff0c;支持多用户协作&#xff1b; 甘特图显示具体任务清单、时间和任务的进度&#xff1b; 对未完成任务、已完成任务进行分类管…

AIGC|实践探索Langflow集成AzureOpenAI

目录 一、背景 二、AzureOpenAI介绍 三、langflow集成支持AzureOpenAI langflow集成AzureOpenAI联通改造流程&#xff1a; 四、效果演示 一、背景 langflow是一个LangChain UI&#xff0c;它提供了一种交互界面来使用LangChain&#xff0c;通过简单的拖拽即可搭建自己的实…

【文件读取/包含】任意文件读取漏洞 afr_1

1.1漏洞描述 漏洞名称任意文件读取漏洞 afr_1漏洞类型文件读取漏洞等级⭐漏洞环境docker攻击方式 1.2漏洞等级 高危 1.3影响版本 暂无 1.4漏洞复现 1.4.1.基础环境 靶场docker工具BurpSuite 1.4.2.靶场搭建 1.创建docker-compose.yml文件 version: 3.2 services: web: …

图片转excel表格怎么弄?有何密笈?

一般的软件要将图片转excel表格&#xff0c;都需要待识别的图片要有明显清晰的表格线&#xff0c;但金鸣识别则不需要这些条件的限制&#xff0c;即便是无表格线或缺少横线或竖线的图片&#xff0c;也能很好地识别成excel&#xff0c;另外&#xff0c;别的软件一般会限制文件大…

足跟痛筋膜炎最佳的治疗

足跟疼痛最常见的原因是跟腱炎。跟腱是从小腿肌肉到足跟骨的伸展部分。其他原因包括设备不当&#xff0c;走路加重脚跟的冲击力&#xff0c;鞋里面没有足弓的支撑&#xff0c;因为肥胖或怀孕脚弓变平&#xff0c;这可能会增加足跟疼痛的风险。除了跟腱炎外&#xff0c;足底筋膜…

python对数据的处理合集——字典、列表...

1.两个列表的数据对比 ①list2包含了list1,求出list2多余的值 #codingutf-8list1[1,3,5] list2[1,3,5,7,9,11] list[] for i in list2:if i not in list1:list.append(i) print(list)②求出两个列共同的值 ③两个列表合并 #第一种&#xff1a; list1 [1, 2, 3] list2 [4, …