【设计一个缓存--针对各种类型的缓存】
设计一个缓存--针对各种类型的缓存
- 1. 设计顶层接口
- 2. 设计抽象类 -- AbstractCacheManager
- 3. 具体子类
- 3.1 -- AlertRuleItemExpCacheManager
- 3.2 -- AlertRuleItemSrcCacheManager
- 4. 类图关系
1. 设计顶层接口
// 定义为一个泛型接口,提供给抽象类使用
public interface CacheManager<T> {// 获取所有的缓存itemList<T> getAll();// 根据条件获取某些缓存itemList<T> get(Predicate<T> predicate);// 设置缓存boolean set(T t);// 设置缓存listboolean 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> {@Resourceprivate AlertRuleItemExpDao alertRuleItemExpDao;@Overrideprotected 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());}@Overrideprotected void setByCache(AlertRuleItemExpCache alertRuleItemExpCache) {cache.put(alertRuleItemExpCache.getId().toString(), alertRuleItemExpCache);}@Overrideprotected void setByCache(List<AlertRuleItemExpCache> alertRuleItemExpCacheList) {alertRuleItemExpCacheList.parallelStream().forEach(alertRuleItemExpCache ->cache.put(alertRuleItemExpCache.getId().toString(), alertRuleItemExpCache));}@Overrideprotected 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> {@Resourceprivate AlertRuleItemSrcDao alertRuleItemSrcDao;@Overrideprotected 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());}@Overrideprotected void setByCache(AlertRuleItemSrcCache alertRuleItemSrcCache) {cache.put(alertRuleItemSrcCache.getId().toString(), alertRuleItemSrcCache);}@Overrideprotected void setByCache(List<AlertRuleItemSrcCache> alertRuleItemSrcCacheList) {alertRuleItemSrcCacheList.parallelStream().forEach(alertRuleItemSrcCache ->cache.put(alertRuleItemSrcCache.getId().toString(), alertRuleItemSrcCache));}@Overrideprotected List<AlertRuleItemSrcCache> getByCache(Predicate<AlertRuleItemSrcCache> predicate) {return getAllByCache().stream().filter(cache -> predicate.test(cache)).collect(Collectors.toList());}
}
4. 类图关系
相关文章:

【设计一个缓存--针对各种类型的缓存】
设计一个缓存--针对各种类型的缓存 1. 设计顶层接口2. 设计抽象类 -- AbstractCacheManager3. 具体子类3.1 -- AlertRuleItemExpCacheManager3.2 -- AlertRuleItemSrcCacheManager 4. 类图关系 1. 设计顶层接口 // 定义为一个泛型接口,提供给抽象类使用 public interface Cach…...

Django部署时静态文件配置的坑
Django部署时静态文件配置配置的坑 近期有个需求是用django进行开发部署,结果发现静态文件配置的坑是真的多,另外网上很多的内容也讲不清楚原理,就是这样这样,又那样那样,进了不少坑,这里记录一下关于css,…...

Android---网络编程优化
网络请求操作是一个 App 的重要组成部分,程序大多数问题都是和网络请求有关。使用 OkHttp 框架后,可以通过 EventListener 来查看一次网络请求的详细情况。一次完整的网络请求会包含以下几个步骤。 也就是说,一次网络请求的操作是从 DNS 解析…...
《算法通关村——不简单的字符串转换问题》
《算法通关村——不简单的字符串转换问题》 8. 字符串转换整数 (atoi) 请你来实现一个 myAtoi(string s) 函数,使其能将字符串转换成一个 32 位有符号整数(类似 C/C 中的 atoi 函数)。 函数 myAtoi(string s) 的算法如下: 读入…...

给VSCode插上一双AI的翅膀
#AI编程助手哪家好?DevChat“真”好用# 文章目录 前言一、安装DevChat1.1、访问地址1.2、注册1.3、在VSCode里安装DevChat插件1.3.1、未安装状态1.3.2、已安装状态 二、设置Access Key2.1. 点击左下角管理(“齿轮”图标)—命令面板ÿ…...

2023年亚太杯数学建模思路 - 案例:异常检测
文章目录 赛题思路一、简介 -- 关于异常检测异常检测监督学习 二、异常检测算法2. 箱线图分析3. 基于距离/密度4. 基于划分思想 建模资料 赛题思路 (赛题出来以后第一时间在CSDN分享) https://blog.csdn.net/dc_sinor?typeblog 一、简介 – 关于异常…...

机器学习的医疗乳腺癌数据的乳腺癌疾病预测
项目视频讲解:基于机器学习的医疗乳腺癌数据的乳腺癌疾病预测 完整代码数据分享_哔哩哔哩_bilibili 效果演示: 代码: #第一步!导入我们需要的工具 import numpy as np import pandas as pd import matplotlib.pyplot as plt import seaborn as sns %matplotlib inlin…...

解析:什么是生成式AI?与其他类型的AI有何不同?
原创 | 文 BFT机器人 快速浏览一下头条新闻,你会发现生成式AI似乎无处不在。事实上,一些新闻标题甚至可能是通过生成式AI编写的,例如OpenAI旗下的ChatGPT,这个聊天机器人已经展现出了生成看起来像人类所写文本的惊人能力。 当人们…...
国产化项目改造:使用达梦数据库和东方通组件部署,前后端分离框架
前提:前后端分离前后端包都要用war包。 1、springboot后端改变war包 pom文件添加 <packaging>war</packaging>添加依赖,并且支持tomcat<!-- war包 --><dependency><groupId>org.springframework.boot</groupId><…...

Nginx实现负载均衡
Nginx实现负载均衡 负载均衡的作用 1、解决单点故障,让web服务器构成一个集群 2、将请求平均下发给后端的web服务器 负载均衡的软硬件介绍 负载均衡软件: # nginx 四层负载均衡:stream(nginx 1.9版本以后有stream模块&#x…...

SpringCloud 2022有哪些变化
目录 前提条件 AOT支持 Spring Native支持 前提条件 Spring Cloud 2022.0.0是构建在Spring Framework 6.0和Spring Boot 3.0 之上的一S个主要版本。 JDK要求最低需要是Java 17J2EE要求最低需要Jakarta EE 9 AOT支持 Spring cloud 2022支持AOT编译,它是将程序源…...

如何快速本地搭建悟空CRM结合内网穿透工具高效远程办公
🌈个人主页:聆风吟 🔥系列专栏:数据结构、Cpolar杂谈 🔖少年有梦不应止于心动,更要付诸行动。 文章目录 📋前言一. 无需公网IP,使用cpolar实现悟空CRM远程访问二. 通过公网来访问公司…...
Docker打包Python项目
1. 简介 Docker是一种开源的容器化平台,可以将应用程序及其依赖项打包到一个轻量级、可移植的容器中。通过使用Docker,可以简化Python项目的部署和运行,提高开发效率和应用程序的可移植性。 本文将介绍如何使用Docker来打包Python项目。我们…...
【Java并发编程一】并发与并行
为什么引入并发 摩尔定理逐渐失效,单核性能很难提升,通过组合多核性能来进一步满足实际需要,从而引入并发编程。在大部分场景下,并行是由于串行的,并行可以优化非关键节点的时间消耗。 并发的三大特性 原子性 某个…...
MFC/QT 一些快忘记的细节:
1:企业应用中,MFC平台除了用常见的对话框模式还有一种常用的就是单文档模式, 维护别人的代码,不容易区分,看它与程预序认同名cpp,就知道了,比如项目名称为 DoCMFCDemo,那么就看BOOL CDocMFCDe…...
在服务器上部署MVC 6应用程序
在服务器上成功部署MVC 6应用程序(现在更为称为ASP.NET Core MVC)涉及一系列步骤。以下是一般的指导步骤: 1. 准备服务器环境: - 确保服务器上安装了.NET Core Runtime和.NET Core SDK。可以从[.NET下载页面](https://dotnet.mi…...

golang学习笔记——斐波纳契数列
斐波纳契数列 编写一个程序来计算某个数字的斐波纳契数列。 斐波那契数列是一个数字列表,其中每个数字是前两个斐波那契数字之和。 例如,数字 6 的序列是 1,1,2,3,5,8,数字 7 的序列是 1,1,2,3,5,8,13,数字 8 的序列是 1,1,2,3,5…...
学习raft协议(1)
CAP C: 一致性 强调数据的正确性,每次读操作,要么读到最新,要么读失败 A:可用性 不发生错误,也不能出现过长的等待时间. P:分区容错性 在网络环境不可靠的背景下,整个系统仍然是正常运作的两种流派 (1&am…...
SpringSecurity+jwt使用
参考文章链接 自定义SpringSecurity用户 package com.daben.springsecurityjwt.vo;import com.daben.springsecurityjwt.entity.SysUser; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.userdetails.User; import j…...

html-网站菜单-点击显示导航栏
一、效果图 1.点击显示菜单栏,点击x号关闭; 2.点击一级菜单,展开显示二级,并且加号变为减号; 3.点击其他一级导航,自动收起展开的导航。 二、代码实现 <!DOCTYPE html> <html><head>&…...
RestClient
什么是RestClient RestClient 是 Elasticsearch 官方提供的 Java 低级 REST 客户端,它允许HTTP与Elasticsearch 集群通信,而无需处理 JSON 序列化/反序列化等底层细节。它是 Elasticsearch Java API 客户端的基础。 RestClient 主要特点 轻量级ÿ…...

多云管理“拦路虎”:深入解析网络互联、身份同步与成本可视化的技术复杂度
一、引言:多云环境的技术复杂性本质 企业采用多云策略已从技术选型升维至生存刚需。当业务系统分散部署在多个云平台时,基础设施的技术债呈现指数级积累。网络连接、身份认证、成本管理这三大核心挑战相互嵌套:跨云网络构建数据…...

调用支付宝接口响应40004 SYSTEM_ERROR问题排查
在对接支付宝API的时候,遇到了一些问题,记录一下排查过程。 Body:{"datadigital_fincloud_generalsaas_face_certify_initialize_response":{"msg":"Business Failed","code":"40004","sub_msg…...
mongodb源码分析session执行handleRequest命令find过程
mongo/transport/service_state_machine.cpp已经分析startSession创建ASIOSession过程,并且验证connection是否超过限制ASIOSession和connection是循环接受客户端命令,把数据流转换成Message,状态转变流程是:State::Created 》 St…...

理解 MCP 工作流:使用 Ollama 和 LangChain 构建本地 MCP 客户端
🌟 什么是 MCP? 模型控制协议 (MCP) 是一种创新的协议,旨在无缝连接 AI 模型与应用程序。 MCP 是一个开源协议,它标准化了我们的 LLM 应用程序连接所需工具和数据源并与之协作的方式。 可以把它想象成你的 AI 模型 和想要使用它…...

【第二十一章 SDIO接口(SDIO)】
第二十一章 SDIO接口 目录 第二十一章 SDIO接口(SDIO) 1 SDIO 主要功能 2 SDIO 总线拓扑 3 SDIO 功能描述 3.1 SDIO 适配器 3.2 SDIOAHB 接口 4 卡功能描述 4.1 卡识别模式 4.2 卡复位 4.3 操作电压范围确认 4.4 卡识别过程 4.5 写数据块 4.6 读数据块 4.7 数据流…...
Linux云原生安全:零信任架构与机密计算
Linux云原生安全:零信任架构与机密计算 构建坚不可摧的云原生防御体系 引言:云原生安全的范式革命 随着云原生技术的普及,安全边界正在从传统的网络边界向工作负载内部转移。Gartner预测,到2025年,零信任架构将成为超…...
汇编常见指令
汇编常见指令 一、数据传送指令 指令功能示例说明MOV数据传送MOV EAX, 10将立即数 10 送入 EAXMOV [EBX], EAX将 EAX 值存入 EBX 指向的内存LEA加载有效地址LEA EAX, [EBX4]将 EBX4 的地址存入 EAX(不访问内存)XCHG交换数据XCHG EAX, EBX交换 EAX 和 EB…...

AI病理诊断七剑下天山,医疗未来触手可及
一、病理诊断困局:刀尖上的医学艺术 1.1 金标准背后的隐痛 病理诊断被誉为"诊断的诊断",医生需通过显微镜观察组织切片,在细胞迷宫中捕捉癌变信号。某省病理质控报告显示,基层医院误诊率达12%-15%,专家会诊…...
【Go语言基础【12】】指针:声明、取地址、解引用
文章目录 零、概述:指针 vs. 引用(类比其他语言)一、指针基础概念二、指针声明与初始化三、指针操作符1. &:取地址(拿到内存地址)2. *:解引用(拿到值) 四、空指针&am…...