【设计一个缓存--针对各种类型的缓存】
设计一个缓存--针对各种类型的缓存
- 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>&…...

SpringBoot-17-MyBatis动态SQL标签之常用标签
文章目录 1 代码1.1 实体User.java1.2 接口UserMapper.java1.3 映射UserMapper.xml1.3.1 标签if1.3.2 标签if和where1.3.3 标签choose和when和otherwise1.4 UserController.java2 常用动态SQL标签2.1 标签set2.1.1 UserMapper.java2.1.2 UserMapper.xml2.1.3 UserController.ja…...
在软件开发中正确使用MySQL日期时间类型的深度解析
在日常软件开发场景中,时间信息的存储是底层且核心的需求。从金融交易的精确记账时间、用户操作的行为日志,到供应链系统的物流节点时间戳,时间数据的准确性直接决定业务逻辑的可靠性。MySQL作为主流关系型数据库,其日期时间类型的…...
大语言模型如何处理长文本?常用文本分割技术详解
为什么需要文本分割? 引言:为什么需要文本分割?一、基础文本分割方法1. 按段落分割(Paragraph Splitting)2. 按句子分割(Sentence Splitting)二、高级文本分割策略3. 重叠分割(Sliding Window)4. 递归分割(Recursive Splitting)三、生产级工具推荐5. 使用LangChain的…...
Robots.txt 文件
什么是robots.txt? robots.txt 是一个位于网站根目录下的文本文件(如:https://example.com/robots.txt),它用于指导网络爬虫(如搜索引擎的蜘蛛程序)如何抓取该网站的内容。这个文件遵循 Robots…...

多模态大语言模型arxiv论文略读(108)
CROME: Cross-Modal Adapters for Efficient Multimodal LLM ➡️ 论文标题:CROME: Cross-Modal Adapters for Efficient Multimodal LLM ➡️ 论文作者:Sayna Ebrahimi, Sercan O. Arik, Tejas Nama, Tomas Pfister ➡️ 研究机构: Google Cloud AI Re…...
全面解析各类VPN技术:GRE、IPsec、L2TP、SSL与MPLS VPN对比
目录 引言 VPN技术概述 GRE VPN 3.1 GRE封装结构 3.2 GRE的应用场景 GRE over IPsec 4.1 GRE over IPsec封装结构 4.2 为什么使用GRE over IPsec? IPsec VPN 5.1 IPsec传输模式(Transport Mode) 5.2 IPsec隧道模式(Tunne…...

Unity | AmplifyShaderEditor插件基础(第七集:平面波动shader)
目录 一、👋🏻前言 二、😈sinx波动的基本原理 三、😈波动起来 1.sinx节点介绍 2.vertexPosition 3.集成Vector3 a.节点Append b.连起来 4.波动起来 a.波动的原理 b.时间节点 c.sinx的处理 四、🌊波动优化…...
【Nginx】使用 Nginx+Lua 实现基于 IP 的访问频率限制
使用 NginxLua 实现基于 IP 的访问频率限制 在高并发场景下,限制某个 IP 的访问频率是非常重要的,可以有效防止恶意攻击或错误配置导致的服务宕机。以下是一个详细的实现方案,使用 Nginx 和 Lua 脚本结合 Redis 来实现基于 IP 的访问频率限制…...
Python Einops库:深度学习中的张量操作革命
Einops(爱因斯坦操作库)就像给张量操作戴上了一副"语义眼镜"——让你用人类能理解的方式告诉计算机如何操作多维数组。这个基于爱因斯坦求和约定的库,用类似自然语言的表达式替代了晦涩的API调用,彻底改变了深度学习工程…...
比较数据迁移后MySQL数据库和OceanBase数据仓库中的表
设计一个MySQL数据库和OceanBase数据仓库的表数据比较的详细程序流程,两张表是相同的结构,都有整型主键id字段,需要每次从数据库分批取得2000条数据,用于比较,比较操作的同时可以再取2000条数据,等上一次比较完成之后,开始比较,直到比较完所有的数据。比较操作需要比较…...