【JAVA】利用Redisson和Spring实现高效物联温度控制链路,确保温度调节的准确性和效率,定时链路执行使用案例,一环扣一环
主要功能和场景
-
柔性调温策略:这个类主要用于管理一个温度调节流程,通过不同的策略(如策略1和策略2)来调节温度,确保设备或环境中的温度达到预设的目标。
-
紧急停止机制:在流程执行过程中,如果需要紧急停止,可以通过设置一个标志来立即停止所有正在进行的任务。
-
定时任务管理:使用Java的
ScheduledExecutorService
来管理定时任务,如定期检查温度、执行特定的温度调节策略等。 -
Redis集成:使用Redisson客户端与Redis数据库交互,存储和检索紧急停止的状态。
代码详细描述
-
类结构:
- 使用
@Slf4j
注解来自动生成日志记录器。 - 使用
@RequiredArgsConstructor
注解来自动注入对象
- 使用
-
常量定义:
STRATEGY_DURATION
:定义了策略的持续时间,这里是5分钟减去30秒。EMERGENCY_STOPPED_KEY
:在Redis中存储紧急停止状态的键。EMERGENCY_STOPPED
和RESTART_STOPPED
:分别代表紧急停止和重启的状态。
-
方法:
startProcessChain(Long planId)
:启动整个流程,首先检查是否需要紧急停止,然后开始执行柔性调温策略1。applyFlexibleTempStrategy1(Long planId)
和applyFlexibleTempStrategy2(Long planId)
:分别实现策略1和策略2,包括下发温度调节指令和召测命令,以及根据召测结果调整策略。waitFor5MinutesAfterStrategy1(Long planId)
和waitFor10MinutesAfterStrategy2(Long planId)
:在策略1和策略2之后等待一定时间,然后执行下一步。applyTargetPower(Long planId)
:在策略2之后执行目标功率控制。waitFor10MinutesBeforeStop(Long planId)
:在停止前等待10分钟。emergencyStop(Long planId)
和restart(Long planId)
:分别用于紧急停止流程和重启流程。isEmergencyStopped(Long planId)
和setEmergencyStopped(Long planId)
:用于检查和设置紧急停止状态。
使用场景
这个类适用于需要精确控制温度的场景,如数据中心、实验室或工业生产环境,其中温度的精确控制对于设备的正常运行至关重要。通过这个流程管理器,可以确保在各种情况下都能有效地调节温度,同时提供紧急停止机制以应对突发情况。
在ProcessManager
类中,每个流程都创建了一个ScheduledExecutorService
实例,通过Executors.newScheduledThreadPool(1)
创建了一个大小为1的线程池。这种设计有几个好处:
-
资源控制:通过限制线程池的大小为1,可以确保每个流程在其生命周期内只使用一个线程。这有助于防止资源过度消耗,特别是在高并发环境中,可以避免因创建过多线程而导致的系统资源耗尽。
-
任务串行执行:由于线程池大小为1,所有提交给该线程池的任务将按顺序串行执行。这意味着一个流程中的所有任务都是顺序执行的,不会并发执行,这有助于简化任务之间的同步和数据依赖问题。
-
简化同步:在某些情况下,流程中的任务可能需要访问共享资源或状态,串行执行可以减少或消除对这些资源进行复杂同步的需求,因为任务不会并发地访问这些资源。
-
避免竞态条件:在单线程环境中,不会出现竞态条件(race conditions),因为任务是按顺序执行的。这对于确保流程的正确性和可预测性非常重要。
-
易于管理:单线程池使得任务的管理和监控更加简单。例如,如果需要取消所有任务,只需调用
scheduler.shutdown()
即可。 -
适合定时任务:
ScheduledExecutorService
特别适合执行定时任务,如周期性任务或延迟任务。通过使用单线程池,可以确保这些任务按照预定的时间表执行,而不会因为线程争用而产生时间偏差。
总之,为每个流程创建一个单线程的ScheduledExecutorService
可以提供一个简单、可控且高效的方式来管理流程中的定时任务,同时确保流程的稳定性和可预测性。
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.dromara.hutool.core.text.CharSequenceUtil;
import org.redisson.api.RBucket;
import org.redisson.api.RedissonClient;
import org.springframework.stereotype.Component;import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;/*** 能力认定流程manager*/
@Slf4j
@Component
@RequiredArgsConstructor
public class ProcessManager {/*** 5分钟,单位为毫秒(策略持续时间),30秒执行一次,减少30秒是由于第一次进入默认执行一次召测*/private static final long STRATEGY_DURATION = 5 * 60 * 1000 - 30000;/*** Redis中存储紧急停止值*/private static final String EMERGENCY_STOPPED_KEY = "IOT:EMERGENCY:STOPPED:VAL:";/*** 紧急停止值*/private static final String EMERGENCY_STOPPED = "1";/*** 重启*/private static final String RESTART_STOPPED = "0";/*** Redisson客户端*/private final RedissonClient redissonClient;/*** 启动任务*/public void startProcessChain(Long planId) {// 否紧急停止if (isEmergencyStopped(planId)) {return;}ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);log.info("Step 0 startProcessChain with task ID: " + planId);// 立即执行柔性调温策略1scheduler.schedule(() -> applyFlexibleTempStrategy1(planId), 0, TimeUnit.SECONDS);// 立马取消当前任务scheduler.shutdown();}/*** 柔性调温策略1*/private void applyFlexibleTempStrategy1(Long planId) {// 紧急停止if (isEmergencyStopped(planId)) {return;}log.info("Step 1 下发遥调指令task ID: " + planId);// 下发遥调指令String tempValue = "18";// 下发遥调任务失败,流程结束if (packageCommandTempIssuance()) {return;}long startTime = System.currentTimeMillis();// 整个流程持续五分钟,30秒执行一次ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);scheduler.scheduleAtFixedRate(() -> {// 紧急停止if (isEmergencyStopped(planId)) {return;}log.info("Step 1 下发召测命令 task ID: " + planId);int unConformNum = packageCallForTest();// 不满足数量=0时表示都满足18° ± 0.5°,立即执行下一步if (unConformNum == 0) {log.info("Step 1 策略1条件已满足,执行下一步等待 task ID: " + planId);// 满足条件立马执行:"等待五分钟"策略scheduler.schedule(() -> waitFor5MinutesAfterStrategy1(planId), 0, TimeUnit.SECONDS);// 立马取消当前任务scheduler.shutdown();}long elapsedTime = System.currentTimeMillis() - startTime;// 5分钟内所有通道温度未达到18° ± 0.5°,任务终止if (unConformNum != 0 && elapsedTime >= STRATEGY_DURATION) {log.info("Step 1 下发召测命令不满足要求:planId:{},不满足数量:{} ", planId, unConformNum);emergencyStop(planId);scheduler.shutdown();}}, 0, 30, TimeUnit.SECONDS);}/*** 柔性调温策略1之后等待五分钟:配置码值动态获取*/private void waitFor5MinutesAfterStrategy1(Long planId) {// 紧急停止if (isEmergencyStopped(planId)) {return;}String value = "5";log.info("After step 1 waiting for " + value + " minutes for task ID: " + planId);ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);// 五分钟之后执行applyFlexibleTempStrategy2scheduler.schedule(() -> applyFlexibleTempStrategy2(planId), Long.parseLong(value),TimeUnit.MINUTES);// 立马取消当前任务scheduler.shutdown();}/*** 柔性调温策略2*/private void applyFlexibleTempStrategy2(Long planId) {// 紧急停止if (isEmergencyStopped(planId)) {return;}log.info("Step 2 策略2下发遥调指令 task ID: " + planId);// 下发遥调指令String tempValue = "26";// 下发遥调任务失败,流程结束if (packageCommandTempIssuance()) {emergencyStop(planId);return;}long startTime = System.currentTimeMillis();// 整个流程持续五分钟ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);scheduler.scheduleAtFixedRate(() -> {// 紧急停止if (isEmergencyStopped(planId)) {return;}log.info("Step 2 策略2下发召测指令 task ID: " + planId);int unConformNum = packageCallForTest();// 不满足数量=0时表示都满足26° ± 0.5°,立即执行下一步if (unConformNum == 0) {log.info("Step 2 策略2条件已满足,执行下一步等待 task ID: " + planId);// 满足条件立马执行:"等待五分钟"策略scheduler.schedule(() -> waitFor10MinutesAfterStrategy2(planId), 0, TimeUnit.SECONDS);// 立马取消当前任务scheduler.shutdown();}long elapsedTime = System.currentTimeMillis() - startTime;// 5分钟内所有通道温度未达到26° ± 0.5°,任务终止if (unConformNum != 0 && elapsedTime >= STRATEGY_DURATION) {log.info("Step 2 下发召测命令不满足要求:planId:{},不满足数量:{} ", planId, unConformNum);emergencyStop(planId);// 立马取消当前任务scheduler.shutdown();}}, 0, 30, TimeUnit.SECONDS);}/*** 柔性调温策略2之后等10分钟:配置码值动态获取*/private void waitFor10MinutesAfterStrategy2(Long planId) {if (isEmergencyStopped(planId)) {return;}String value = "10";log.info("After step 2 Waiting for " + value + " minutes task: " + planId);ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);// 等10分钟目标功率控制scheduler.schedule(() -> applyTargetPower(planId), Long.parseLong(value), TimeUnit.MINUTES);// 立马取消当前任务scheduler.shutdown();}/*** 目标功率控制*/private void applyTargetPower(Long planId) {if (isEmergencyStopped(planId)) {return;}log.info("Step 3 目标功率控制 task ID: " + planId);// 下发遥调任务失败,流程结束if (packageCommandTempIssuance()) {emergencyStop(planId);return;}ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);// 立即执行停止前等待10分钟scheduler.schedule(() -> waitFor10MinutesBeforeStop(planId), 0,TimeUnit.SECONDS);// 立马取消当前任务scheduler.shutdown();}/*** 停止前等待10分钟:配置码值动态获取*/private void waitFor10MinutesBeforeStop(Long planId) {// 紧急停止if (isEmergencyStopped(planId)) {return;}String tempValue = "10";log.info("After step 3 wait for " + tempValue + " minutes task ID: " + planId);ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);scheduler.schedule(() -> {log.info("waitFor10MinutesBeforeStop step 4 stop task ID: " + planId);// 立马取消当前任务scheduler.shutdown();}, Long.parseLong(tempValue), TimeUnit.MINUTES);}/*** 紧急停止*/public void emergencyStop(Long planId) {log.info("Emergency stopping the process with task ID: " + planId);setEmergencyStopped(planId);}/*** 重启一键能力认证流程*/public void restart(Long planId) {// 1:true,0:falseredissonClient.getBucket(EMERGENCY_STOPPED_KEY + planId).set(RESTART_STOPPED);}/*** 是否紧急停止*/private boolean isEmergencyStopped(Long planId) {RBucket < String > bucket = redissonClient.getBucket(EMERGENCY_STOPPED_KEY + planId);String isEmergencyStopped = bucket.get();return isEmergencyStopped != null && CharSequenceUtil.equals(isEmergencyStopped, EMERGENCY_STOPPED);}/*** 设置紧急停止值*/private void setEmergencyStopped(Long planId) {// 1:true,0:falseredissonClient.getBucket(EMERGENCY_STOPPED_KEY + planId).set(EMERGENCY_STOPPED);}/*** 下发遥调指令*/private boolean packageCommandTempIssuance() {// 下发遥调指令,示意代码return true;}/*** 下发召测命令** @return 不满足数量*/private Integer packageCallForTest() {// 下召测命令,拿内机数据,示意代码return 0;}
}
相关文章:
【JAVA】利用Redisson和Spring实现高效物联温度控制链路,确保温度调节的准确性和效率,定时链路执行使用案例,一环扣一环
主要功能和场景 柔性调温策略:这个类主要用于管理一个温度调节流程,通过不同的策略(如策略1和策略2)来调节温度,确保设备或环境中的温度达到预设的目标。 紧急停止机制:在流程执行过程中,如果需…...

yolov8部署资料
1.labelImg安装: labelImg的安装过程可以参照以下步骤进行,这里以Windows操作系统为例: 1. 检查Python环境 首先,需要确认你的电脑上是否已经安装了Python。你可以通过Win R打开windows“运行”对话框,输入cmd&#x…...

迅为RK3588开发板支持LVDS信号,标准 HDMI信号,IMIPI信号
性能强--iTOP-3588开发板采用瑞芯微RK3588处理器,是全新一代ALoT高端应用芯片,采用8nm LP制程,搭载八核64位CPU,四核Cortex-A76和四核Cortex-A55架构,主频高达2.4GHZ,8GB内存,32GB EMMC。 四核心…...

页面开发感想
页面开发 1、 前端预览 2、一些思路 2.1、首页自定义element-plus的走马灯 :deep(.el-carousel__arrow){border-radius: 0%;height: 10vh; }需要使用:deep(标签)才能修改样式 或者 ::v-deep 标签 2.2、整体设计思路 <template><div class"card" style&…...

TikTok达人合作ROI分析:品牌如何评估带货效果
在当今的数字营销时代,TikTok已经成为品牌推广和消费者互动的重要平台。通过与TikTok达人的合作,品牌可以有效地提升其市场影响力和销售额。其中,评估这些合作的投入产出比(ROI)对于品牌来说是至关重要的。本文Nox聚星…...

硬件实用技巧:电容精度和常用容值表
若该文为原创文章,转载请注明原文出处 本文章博客地址:https://hpzwl.blog.csdn.net/article/details/140009042 长沙红胖子Qt(长沙创微智科)博文大全:开发技术集合(包含Qt实用技术、树莓派、三维、OpenCV…...

Java面试题:内存管理、类加载机制、对象生命周期及性能优化
1. 说一下 JVM 的主要组成部分及其作用? JVM包含两个子系统和两个组件:Class loader(类装载)、Execution engine(执行引擎)、Runtime data area(运行时数据区)、Native Interface(本地接口)。 Class loader(类装载):根据给定的全限定名类名(如:java.lang.Object)装载class文…...
什么是 Payment Request API?
Payment Request API 是一个 Web API,允许网页和 Web 应用程序向用户展示一个标准化的支付界面,以便用户快速、方便地进行付款。这种 API 的设计目的是为了简化用户支付过程,提高支付转化率,并提供一种更加统一的支付体验。 支持…...
【杂记-浅谈EBGP外部边界网关协议、IBGP内部边界网关协议】
一、EBGP概述 EBGP,External Border Gateway Protocol,即外部边界网关协议,EBGP主要用于在不同自治系统(AS)之间交换路由信息,每个AS都有一个独特的AS号码,用于区分不同的自治系统。EBGP通过AS…...

基于Java的宠物领养管理系统【附源码】
摘 要 近些年来,随着科技的飞速发展,互联网的普及逐渐延伸到各行各业中,给人们生活带来了十分的便利,宠物管理系统利用计算机网络实现信息化管理,使整个宠物领养的发展和服务水平有显著提升。 本文拟采用IDEA开发工具…...
Grafana 对接 Zabbix 数据源API错误
介绍 主要报错为 Invalid params. Invalid parameter "/": unexpected parameter "user". 主要原因为Zabbix 6.4.0以上的版本更新了API,导致Grafana的数据源插件不兼容。 解决方案 更新到最新的Grafana 和 grafana-zabbix 插件即可。&#x…...
Spring Boot与Apache Kafka的深度集成
Spring Boot与Apache Kafka的深度集成 大家好,我是免费搭建查券返利机器人省钱赚佣金就用微赚淘客系统3.0的小编,也是冬天不穿秋裤,天冷也要风度的程序猿!今天我们将探讨如何在Spring Boot应用中实现与Apache Kafka的深度集成&am…...

07 Pytoch Module
1.继承nn.Module 2.class A (B) 进入到 super_init() 3.进入construct() 初始化参数 同时判断是否为train 4.跳出来:进入了 forward 中 5.子模块的构建 nn.Module总结 一个module可以包含多个子module 一个module相当于一个运算,必须实现…...

Isaac Sim 9 物理(1)
使用Python USD API 来实现 Physics 。 以下内容中,大部分 Python 代码可以在 Physics Python 演示脚本文件中找到,本文仅作为个人学习笔记。 一.设置 USD Stage 和物理场景 Setting up a USD Stage and a Physics Scene USD Stage不知道怎么翻译&#…...
vue vue.config.js webpack 加密混淆代码
一、下载加密插件 webpack-obfuscator npm install --save-dev webpack-obfuscatorVue CLI 本身依赖于 Webpack 进行构建和打包。不需要单独安装 Webpack 二、配置vue.config.js const { defineConfig } require(vue/cli-service) const WebpackObfuscator require(webpac…...

Talk|北京大学PKU-DAIR余昭辰:从多模态理解到生成 - 从LLM到Diffusion Model
本期为TechBeat人工智能社区第603期线上Talk。 北京时间6月26日(周三)20:00,北京大学PKU-DAIR实习生—余昭辰的Talk已经准时在TechBeat人工智能社区开播! 他与大家分享的主题是: “从多模态理解到生成 - 从LLM到Diffusion Model”,在本次Talk…...
数据中台高频面试题及参考答案(持续更新)
做大数据开发的,个人感觉招人最多的是是数据中台和数据仓库领域的。所以对数据中台、数据仓库相关的面试题要熟悉。 什么是数据中台?它与传统数据仓库的区别是什么? 数据中台是一种企业级的数据管理和分析平台,旨在通过集成、处理和分析来自企业内外部的大量多样化的数据…...

腾讯云CVM,CentOS8系统下部署Java-Web项目步骤详解
在CVM中部署项目首先要配置好JDK,Tomcat,Mysql(这里以Tomcat和Mysql为例)。部署JDK和Tomcat的步骤可以参考 CentOS7系统下部署tomcat,浏览器访问localhost:8080/_不积跬步,无以至千里;不积小流,无以成江河。-CSDN博客 我这里从Mysql的安装和设…...

Jenkins 创建流水线任务
Jenkins是一个流行的持续集成(Continuous Integration,CI)工具。 Jenkins 创建任务 选择“流水线”类型,该类型的优点是定制化程度非常高 (可选)添加“参数化构建” 配置仓库选项(ssh连接、分支)和凭据…...

单总线协议耗材认证加密芯片ALPU-P
这是一款采用随机变量交换系统的认证加密芯片。ALPU-P与系统MCU以密码方式通信,MCU在诸如系统启动等关键场合检测ALPU-P加密芯片。所以即使盗版系统复制了PCB、内核甚至存储器中的固件,但若缺少ALPU-P芯片,该系统仍然无法工作。 加密芯片是对…...
论文解读:交大港大上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架(二)
HoST框架核心实现方法详解 - 论文深度解读(第二部分) 《Learning Humanoid Standing-up Control across Diverse Postures》 系列文章: 论文深度解读 + 算法与代码分析(二) 作者机构: 上海AI Lab, 上海交通大学, 香港大学, 浙江大学, 香港中文大学 论文主题: 人形机器人…...

如何在看板中体现优先级变化
在看板中有效体现优先级变化的关键措施包括:采用颜色或标签标识优先级、设置任务排序规则、使用独立的优先级列或泳道、结合自动化规则同步优先级变化、建立定期的优先级审查流程。其中,设置任务排序规则尤其重要,因为它让看板视觉上直观地体…...

第一篇:Agent2Agent (A2A) 协议——协作式人工智能的黎明
AI 领域的快速发展正在催生一个新时代,智能代理(agents)不再是孤立的个体,而是能够像一个数字团队一样协作。然而,当前 AI 生态系统的碎片化阻碍了这一愿景的实现,导致了“AI 巴别塔问题”——不同代理之间…...

RNN避坑指南:从数学推导到LSTM/GRU工业级部署实战流程
本文较长,建议点赞收藏,以免遗失。更多AI大模型应用开发学习视频及资料,尽在聚客AI学院。 本文全面剖析RNN核心原理,深入讲解梯度消失/爆炸问题,并通过LSTM/GRU结构实现解决方案,提供时间序列预测和文本生成…...

html-<abbr> 缩写或首字母缩略词
定义与作用 <abbr> 标签用于表示缩写或首字母缩略词,它可以帮助用户更好地理解缩写的含义,尤其是对于那些不熟悉该缩写的用户。 title 属性的内容提供了缩写的详细说明。当用户将鼠标悬停在缩写上时,会显示一个提示框。 示例&#x…...

OPENCV形态学基础之二腐蚀
一.腐蚀的原理 (图1) 数学表达式:dst(x,y) erode(src(x,y)) min(x,y)src(xx,yy) 腐蚀也是图像形态学的基本功能之一,腐蚀跟膨胀属于反向操作,膨胀是把图像图像变大,而腐蚀就是把图像变小。腐蚀后的图像变小变暗淡。 腐蚀…...
JS设计模式(4):观察者模式
JS设计模式(4):观察者模式 一、引入 在开发中,我们经常会遇到这样的场景:一个对象的状态变化需要自动通知其他对象,比如: 电商平台中,商品库存变化时需要通知所有订阅该商品的用户;新闻网站中࿰…...

论文阅读:Matting by Generation
今天介绍一篇关于 matting 抠图的文章,抠图也算是计算机视觉里面非常经典的一个任务了。从早期的经典算法到如今的深度学习算法,已经有很多的工作和这个任务相关。这两年 diffusion 模型很火,大家又开始用 diffusion 模型做各种 CV 任务了&am…...

密码学基础——SM4算法
博客主页:christine-rr-CSDN博客 专栏主页:密码学 📌 【今日更新】📌 对称密码算法——SM4 目录 一、国密SM系列算法概述 二、SM4算法 2.1算法背景 2.2算法特点 2.3 基本部件 2.3.1 S盒 2.3.2 非线性变换 编辑…...

react-pdf(pdfjs-dist)如何兼容老浏览器(chrome 49)
之前都是使用react-pdf来渲染pdf文件,这次有个需求是要兼容xp环境,xp上chrome最高支持到49,虽然说iframe或者embed都可以实现预览pdf,但为了后续的定制化需求,还是需要使用js库来渲染。 chrome 49测试环境 能用的测试…...