本地缓存数据存入文件中

文章目录

  • 演示代码
    • 本地缓存数据存入文件
    • 从文件提取数据到本地缓存
    • 工具类
  • 实战
    • 初始化操作
    • 执行 本地缓存数据存入文件 的线程任务
    • 持久化工具类

演示代码

本地缓存数据存入文件

  public static void testQ15() {LinkedBlockingDeque<ConcurrentHashMap<String, ConcurrentHashMap<Integer, Integer>>> failureStatusCache = new LinkedBlockingDeque<>(4);LinkedBlockingDeque<ConcurrentHashMap<String, ConcurrentHashMap<Integer, Integer>>> successStatusCache = new LinkedBlockingDeque<>(4);LinkedBlockingDeque<ConcurrentHashMap<String, Integer>> pushedStateCache = new LinkedBlockingDeque<>(4);ObjectOutputStream oos = null;//        初始化数据ConcurrentHashMap<String, ConcurrentHashMap<Integer, Integer>> mapF = new ConcurrentHashMap<>();mapF.put("失败数据", new ConcurrentHashMap<Integer, Integer>() {{put(1, 0);}});failureStatusCache.add(mapF);ConcurrentHashMap<String, ConcurrentHashMap<Integer, Integer>> mapS = new ConcurrentHashMap<>();mapS.put("成功数据", new ConcurrentHashMap<Integer, Integer>() {{put(2, 0);}});successStatusCache.add(mapS);pushedStateCache.add(new ConcurrentHashMap<String, Integer>() {{put("哈哈哈", 3);}});log.info("【SoulCache - saveData】持久化数据到文件");try {oos = new ObjectOutputStream(Files.newOutputStream(Paths.get(PersistencePath.createFile("tzh"))));oos.writeObject(failureStatusCache);oos.writeObject(successStatusCache);oos.writeObject(pushedStateCache);log.info("【SoulCache - saveData】持久化数据到文件 | 结束");} catch (Exception e) {log.error("保存持久化文件异常", e);} finally {try {if (oos != null) {oos.close();}} catch (IOException ioe) {log.error("IO流关闭异常", ioe);}}}

从文件提取数据到本地缓存

  • 提取数据顺序必须和存入顺序一致,不然会报错
public static void testQ16() {ObjectInputStream ois = null;try {String path = PersistencePath.getPath("tzh");log.info("【SoulCache - loadData】加载到内存开始... | path:{}", path);ois = new ObjectInputStream(Files.newInputStream(Paths.get(path)));LinkedBlockingDeque<ConcurrentHashMap<String, ConcurrentHashMap<Integer, Integer>>> failureStatusCache = (LinkedBlockingDeque<ConcurrentHashMap<String, ConcurrentHashMap<Integer, Integer>>>) ois.readObject();LinkedBlockingDeque<ConcurrentHashMap<String, ConcurrentHashMap<Integer, Integer>>> successStatusCache = (LinkedBlockingDeque<ConcurrentHashMap<String, ConcurrentHashMap<Integer, Integer>>>) ois.readObject();LinkedBlockingDeque<ConcurrentHashMap<String, Integer>> pushedStateCache = (LinkedBlockingDeque<ConcurrentHashMap<String, Integer>>) ois.readObject();System.out.println("失败数据:"+failureStatusCache.getFirst().toString());System.out.println("成功数据:"+successStatusCache.getFirst().toString());System.out.println(pushedStateCache.getFirst().toString());log.info("【SoulCache - loadData】加载到内存 结束");} catch (Exception e) {log.error("加载内存持久化文件异常", e);} finally {try {if (ois != null) {ois.close();}PersistencePath.delFile("tzh");} catch (IOException ioe) {log.error("IO流关闭异常", ioe);}}}

工具类

public class PersistencePath {private static final Logger logger = LoggerFactory.getLogger(PersistencePath.class);/*** 定时快照*      ps:只针对状态报告*/private static AtomicInteger aofVersion = new AtomicInteger(0);/*** Docker容器中对应持久化目录,挂载到宿主机的相同名称目录*   /test:./PersistenceData*/private final static String path = "/Users/zeki/test/";//服务id  需要在不同的实现工程中自己去注入值   例如在网关项目中代表网关idpublic static String serverId="1";//服务名称   需要在不同的实现工程中自己去注入值public static String serverName="titan";private static String getAofVersion(){String _v = DateUtil.formatDateyyyyMMddHHmmss(System.currentTimeMillis()) + "_" + aofVersion.get();aofVersion.incrementAndGet();return _v;}/*** 持久化文件的名字  与服务名、服务id有关*    ps:  例子    视频网关集群里面网关id为1的持久化文件名称为  sms-vms-gateway1.obj* @return*/private static String buildFileName(){return String.format("%s%s.obj", Optional.ofNullable(serverName).orElse(defaultServerName()), serverId);}/*** 持久化文件的名字  与服务名、服务id有关*    ps:  例子    视频网关集群里面网关id为1的持久化文件名称为  sms-vms-gateway1.obj20210407120000_1* @return*/private static String buildFileName_AOF(){return buildFileName().concat(getAofVersion());}/*** 持久化文件的名字  与服务名、服务id有关*    ps:  例子    视频网关集群里面网关id为1的持久化文件名称为  sms-vms-gateway1.obj* @param prefixName 可能一个应用系统里面会有多个持久化文件   通过这个参数指定名称* @return*/private static String buildFileName(String prefixName){return String.format("%s%s_%s.obj", Optional.ofNullable(serverName).orElse(defaultServerName()), serverId, prefixName);}/*** 获取文件路径* @return 文件存在,返回文件路径,不存在,返回null* @throws IOException*/public static String getPath() {String fileName = buildFileName();File file = new File(path, fileName);if (file.exists()) {return path + fileName;}logger.warn("getPath {}{} 不存在",path,fileName);return null;}/*** 获取文件路径* @return 文件存在,返回文件路径,不存在,返回null* @throws IOException*/public static String getPath_AOF() {String fileName = buildFileName_AOF();File file = new File(path, fileName);if (file.exists()) {return path + fileName;}return null;}/*** 获取文件路径* @return 文件存在,返回文件路径,不存在,返回null* @param prefixName 可能一个应用系统里面会有多个持久化文件   通过这个参数指定名称* @throws IOException*/public static String getPath(String prefixName) {String fileName = buildFileName(prefixName);File file = new File(path, fileName);if (file.exists()) {return path + fileName;}return null;}/*** 创建文件* @return* @throws IOException*/public static String createFile() throws IOException {String fileName = buildFileName();File file = new File(path, fileName);if (!file.exists()) {	//文件不存在,创建file.createNewFile();}return path + fileName;}/*** 创建文件* @return* @throws IOException*/public static String createFile_AOF() throws IOException {String fileName = buildFileName_AOF();File file = new File(path, fileName);if (!file.exists()) {	//文件不存在,创建file.createNewFile();}return path + fileName;}/*** 创建文件* @param prefixName 可能一个应用系统里面会有多个持久化文件   通过这个参数指定名称* @return* @throws IOException*/public static String createFile(String prefixName) throws IOException {String fileName = buildFileName(prefixName);File file = new File(path, fileName);if (!file.exists()) {	//文件不存在,创建file.createNewFile();}return path + fileName;}/*** 删除文件* @return* @throws IOException*/public static boolean delFile() {String fileName = buildFileName();File file = new File(path, fileName);if (file.exists()) {return file.delete();}return false;}/*** 删除文件* @param prefixName 可能一个应用系统里面会有多个持久化文件   通过这个参数指定名称* @return* @throws IOException*/public static boolean delFile(String prefixName) {String fileName = buildFileName(prefixName);File file = new File(path, fileName);if (file.exists()) {FileUtil.rename(file, String.format("%s_bak_%s_%s",fileName,cn.hutool.core.date.DateUtil.today(),IdUtil.fastSimpleUUID()), false, true);return true;}return false;}/*** 默认服务名*/private static String defaultServerName() {return Optional.ofNullable(SpringUtil.getApplicationContext()).map(ApplicationContext::getApplicationName).orElse("NULL");}
}

实战

初始化操作

  • implements CommandLineRunner项目开始则执行以下代码,做个钩子,项目关闭时会触发该线程业务逻辑
@Overridepublic void run(String... args) {// 狗子Runtime.getRuntime().addShutdownHook(new Thread(shutdownHook));}

执行 本地缓存数据存入文件 的线程任务

  • 这里的init方法是项目一启动会执行,将文件数据放进本地缓存中初始化
  • 这里的run方法是线程执行业务,项目结束运行,钩子触发该业务将本地缓存数据存放进文件中
@Scope(ConfigurableBeanFactory.SCOPE_SINGLETON)
@Component
public class ShutdownHook implements Runnable{private final static Logger log = LoggerFactory.getLogger(ShutdownHook.class);private static final List<Persistence> canBeHookList = new ArrayList<>();@Value("${server-node.id}")private String nodeId;@Value("${spring.application.name}")private String applicationName;@Resourceprivate MonitorThread monitorThread;@PostConstructpublic void init() {PersistencePath.serverId = nodeId;PersistencePath.serverName = applicationName;//对内存数据进行初始化SmsQueueManage.getInstance().loadLocalData();MemoryParamCache.getInstance().loadLocalData();}@Overridepublic void run() {Thread.currentThread().setName("ShutdownHook_Thread");log.info("【sms-rules退出 - Thread:{}】- 钩子回调 开始...",Thread.currentThread().getName());monitorThread.stopMonitorAndAllThread();try {Thread.sleep(1000);} catch (InterruptedException e) {log.error(Thread.currentThread().getName() + ": 线程休眠异常" ,e);}log.info("等待持久化队列管理类 size:{}",canBeHookList.size());for (Persistence q : canBeHookList) {q.saveData();}log.error("【sms-rules退出 - Thread:{}】- 钩子回调 完毕",Thread.currentThread().getName());}public static void add(Persistence p) {canBeHookList.add(p);}public static void remove(Persistence p) {canBeHookList.remove(p);}
}

持久化工具类

public class MemoryParamCache implements Persistence {private final static Logger log = LoggerFactory.getLogger(MemoryParamCache.class);/*** 号段持久化文件名称前缀*/private static final String memoryParamCachePrefixFileName = "memoryParamCache";private volatile static MemoryParamCache instance;private MemoryParamCache(){ShutdownHook.add(this);}public static MemoryParamCache getInstance(){if (null == instance) {synchronized (MemoryParamCache.class) {if (null == instance) {instance = new MemoryParamCache();}}}return instance;}@Overridepublic void saveData() {ObjectOutputStream oos = null;String path = "";try {path = PersistencePath.createFile(memoryParamCachePrefixFileName);log.info("【MemoryParamCache - saveData】持久化内存参数到文件 | 开始 | path:{}",path);oos = new ObjectOutputStream(new FileOutputStream(path));oos.writeObject(RuleSymbol.cityMap);log.info("【MemoryParamCache - saveData】持久化内存参数到文件 | 结束 | path:{} | cityMap:{}",path , RuleSymbol.cityMap.size());} catch (Exception e) {log.error("【MemoryParamCache - 持久化内存参数到文件】异常 | path:{}",path, e);} finally {try {if (oos != null) {oos.close();}} catch (IOException ioe) {// ignore}}}/*** 磁盘上的缓存数据加载到内存*/public void loadLocalData() {ObjectInputStream ois = null;String path = "";try {path = PersistencePath.getPath(memoryParamCachePrefixFileName);log.info("【MemoryParamCache - loadLocalData】内存参数缓存文件-->-->-->-->加载到内存开始... | path:{}",path);ois = new ObjectInputStream(new FileInputStream(path));RuleSymbol.cityMap = (ConcurrentHashMap<String, String>) ois.readObject();log.info("【MemoryParamCache - loadLocalData】内存参数缓存文件-->-->-->-->加载到内存 结束 | path:{} | cityMap:{}",path, RuleSymbol.cityMap.size());}catch (Exception e) {log.error("【sms-rules启动 - 加载持久化后的内存参数】异常 | path:{}", path,e);}finally {if(ois != null){try {ois.close();} catch (IOException e) {// ignore}boolean b = PersistencePath.delFile(memoryParamCachePrefixFileName);log.info("【MemoryParamCache - loadLocalData】STEP-TWO 删除缓存数据文件:{}",b);}}}}

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

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

相关文章

【STM32HAL库】外部中断

目录 一、中断简介 二、NVIC 1.寄存器 2.工作原理 3.优先级 4.使用NVIC 三、EXTI 1.简介 2.AFIO&#xff1a;复用功能IO&#xff0c;主要用于重映射和外部中断映射配置​编辑 3. 中断使用 4.HAL库配置使用 一、中断简介 中断的意义&#xff1a;高效处理紧急程序&#xff0c;不会…

SPRD Android 14 通过属性控制系统设置显示双栏或者单栏

SPRD Android 14 通过属性控制系统设置显示双栏或者单栏 第一步 确认有添加静态库第二步 验证第三步 修改源码在合适的地方配置 ro.product.is_support_SettingsSplitEnabled 即可。第一步 确认有添加静态库 --- a/packages/apps/Settings/Android.bp +++ b/packages/apps/Set…

php反序列化逃逸

php反序列化逃逸 逃逸是php中反序列化时的恶意利用&#xff0c;以ctf为例演示 第一段演示 逃逸为ctf反序列化的内容&#xff0c;主要是对序列化对象进行过滤&#xff0c;其中替换串长度不一致&#xff0c;造成字符逃逸。攻击者可以构造恶意的payload&#xff0c;改变对象中的…

MATLAB循环语句

MATLAB 循环语句 在某些情况下&#xff0c;您需要多次执行一个代码块。通常&#xff0c;语句是按顺序执行的。首先执行函数中的第一条语句&#xff0c;然后执行第二条&#xff0c;依此类推。 编程语言提供了各种控制结构&#xff0c;允许更复杂的执行路径。 循环语句允许我们…

猫头虎分享已解决Bug || **Error: ‘Promise‘ is undefined**

博主猫头虎的技术世界 &#x1f31f; 欢迎来到猫头虎的博客 — 探索技术的无限可能&#xff01; 专栏链接&#xff1a; &#x1f517; 精选专栏&#xff1a; 《面试题大全》 — 面试准备的宝典&#xff01;《IDEA开发秘籍》 — 提升你的IDEA技能&#xff01;《100天精通鸿蒙》 …

3.8设计模式——State 状态模式(行为型)

意图 允许一个对象在其内部状态改变时改变它的行为。对象看起来似乎修改了它的类。 结构 Context&#xff08;上下文&#xff09;定义客户感兴趣的接口&#xff1b;维护一个ConcreteState子类的实例&#xff0c;这个实例定义当前状态。State&#xff08;状态&#xff09;定义…

4 -25

1 100个英语单词两篇六级阅读 2 cf补题&#xff1b; 3 仿b站项目看源码 debug分析业务。 上了一天课&#xff0c;晚上去健身。 物理备课&#xff0c;周六去上课腻。 五一回来毛泽东思想期末考试&#xff0c;概率论期中考试。

冯诺依曼体系结构再谈操作系统

前言 前面对基本的指令、权限以及环境开发的基本工具进行了介绍&#xff0c;本期开始我们将进入系统的的学习&#xff0c;例如我们常听的进程等&#xff0c;在进入进程的学习前我们先要铺垫一下&#xff0c;所以本期我们先来介绍一下冯诺依曼体系结构和再谈操作系统&#xff0…

30 番外5 AHK语法应用实战

番外5 AHK语法应用实战 ahk是一种极其轻量,极其易上手,极其方便好用的脚本语言,对于没有编程基础的人来说,可以轻松掌握. 作为一个强大轻量的工具,ahk主要提供了热键宏操作. 什么是热键宏?简单的理解,就是自定义快捷键. AHK使用场景举例 ahk到底有什么用处呢? 1.把一个按键映…

做亚马逊店铺怎么解决网络问题?

在全球电商市场迅速崛起的背景下&#xff0c;亚马逊已成为众多商家拓展海外市场的首选平台。然而&#xff0c;网络问题始终困扰着亚马逊商家&#xff0c;若不能有效解决&#xff0c;不仅影响工作效率&#xff0c;更可能面临店铺被封禁的风险。本文将详细介绍亚马逊店铺运营遇到…

xgp加速器免费 微软商店xgp用什么加速器

2001年11月14日深夜&#xff0c;比尔盖茨亲自来到时代广场&#xff0c;在午夜时分将第一台Xbox交给了来自新泽西的20岁年轻人爱德华格拉克曼&#xff0c;后者在回忆中说&#xff1a;“比尔盖茨就是上帝。”性能超越顶级PC的Xbox让他们趋之若鹜。2000年3月10日&#xff0c;微软宣…

Vision Pro“裸眼上车”,商汤绝影全新舱内3D交互亮相

2023年&#xff0c;Apple Vision Pro的横空出世让人们领略到了3D交互的魅力&#xff0c;商汤绝影通过深厚的技术研发实力和高效的创新迭代效率&#xff0c;带来两大全新座舱3D交互&#xff1a;3D Gaze高精视线交互和3D动态手势交互。 作为全球首创的能够通过视线定位与屏幕图标…

C语言中整型与浮点型在内存中的存储

今天让我们来看看整型的数据和浮点型的数据在内存中是怎么存储的呢 整型数据在内存中的存储 整型数据在内存中存储的是二进制的补码 正数的话也没什么可说的&#xff0c;原码反码补码都相同 我们来看看负数&#xff1a; 以-5为例 原码&#xff1a;10000000 00000000 00000000 0…

传染病模型SIR及其变体(python版本)

文章目录 传染病模型及其变体1. SI模型1.1代码2. SIS模型2.1 代码3. 基本再生数 basic reproductive number4. SIR模型4.1 代码5. SEIR模型5.1 代码6. SEIJR模型6.1 代码7. SEIJRD模型7.1 代码传染病模型及其变体 1. SI模型 在该模型里面,群体中只有两种人:易感者和感染者。…

Postman之页面简介 V9.31.0

Postman之页面简介 V9.31.0 一、顶部栏二、左部栏三、中部栏四、下部栏 一、顶部栏 &#xff08;1&#xff09;new选项框&#xff0c;生成新建请求、集合、环境等 &#xff08;2&#xff09;import选项框&#xff0c;可以导入文件、文件夹、链接、文本信息等 &#xff08;3&…

ros2_control【B站WMGIII教学学习记录】1

资源 https://www.bilibili.com/video/BV1ku411G7UR? 学习过程中存在bug&#xff0c;记录一下 1 Q:"package ‘joint_state_publisher_gui’ not found, searching: [/home A: sudo apt install ros-humble-joint-state-publisher2 https://fishros.org.cn/forum/to…

go语言并发实战——日志收集系统(八) go语言操作etcd以及利用watch实现对键值的监控

有关包的安装 我们要实现go语言对第三方包的操作需要我们下载第三方包go.etcd.io&#xff0c;下载命令&#xff1a; go get go.etcd.io/etcd/client/v3 ectd的put与get操作 相关函数说明与示例 我们想实现对etcd进行简单的操作的步骤还是比较简单的&#xff0c;在我上一篇文…

爬虫抓取网站数据

Fiddler 配置fiddler工具结合浏览器插件 配置fiddler Tools--Options 抓包技巧 谷歌浏览器开启无痕浏览,使用SwitchyOmega配置好代理端口 Ctrl x 清理所有请求记录,可以删除指定不需要日志方便观察 设置按请求顺序 观察cookie,观察请求hesder cookie和row返回结果 Swit…

【C语言】深入理解KMP算法及C语言实现

一、KMP算法简介 KMP算法&#xff08;Knuth-Morris-Pratt算法&#xff09;是一种高效的字符串匹配算法&#xff0c;由Donald Knuth、James H. Morris和 Vaughan Pratt共同发明。KMP算法的核心思想是当一次字符比较失败时&#xff0c;利用已经得到的部分匹配信息&#xff0c;将模…

vue-project-tree vue3 树形结构展示组件

GitHub&#xff1a;vue-project-tree by one-ccs Gitee&#xff1a;vue-project-tree by one-ccs 遵循 MIT 开源协议 文章目录 vue-project-tree一、使用二、API1、属性2、事件3、方法4、插槽 vue-project-tree 使用 Vue3 TS 实现的树形结构展示组件&#xff0c;有拖拽、排序…