当前位置: 首页 > news >正文

【JAVA】利用Redisson和Spring实现高效物联温度控制链路,确保温度调节的准确性和效率,定时链路执行使用案例,一环扣一环

主要功能和场景

  1. 柔性调温策略:这个类主要用于管理一个温度调节流程,通过不同的策略(如策略1和策略2)来调节温度,确保设备或环境中的温度达到预设的目标。

  2. 紧急停止机制:在流程执行过程中,如果需要紧急停止,可以通过设置一个标志来立即停止所有正在进行的任务。

  3. 定时任务管理:使用Java的ScheduledExecutorService来管理定时任务,如定期检查温度、执行特定的温度调节策略等。

  4. Redis集成:使用Redisson客户端与Redis数据库交互,存储和检索紧急停止的状态。

代码详细描述

  • 类结构

    • 使用@Slf4j注解来自动生成日志记录器。
    • 使用@RequiredArgsConstructor注解来自动注入对象
  • 常量定义

    • STRATEGY_DURATION:定义了策略的持续时间,这里是5分钟减去30秒。
    • EMERGENCY_STOPPED_KEY:在Redis中存储紧急停止状态的键。
    • EMERGENCY_STOPPEDRESTART_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,可以确保每个流程在其生命周期内只使用一个线程。这有助于防止资源过度消耗,特别是在高并发环境中,可以避免因创建过多线程而导致的系统资源耗尽。

  2. 任务串行执行:由于线程池大小为1,所有提交给该线程池的任务将按顺序串行执行。这意味着一个流程中的所有任务都是顺序执行的,不会并发执行,这有助于简化任务之间的同步和数据依赖问题。

  3. 简化同步:在某些情况下,流程中的任务可能需要访问共享资源或状态,串行执行可以减少或消除对这些资源进行复杂同步的需求,因为任务不会并发地访问这些资源。

  4. 避免竞态条件:在单线程环境中,不会出现竞态条件(race conditions),因为任务是按顺序执行的。这对于确保流程的正确性和可预测性非常重要。

  5. 易于管理:单线程池使得任务的管理和监控更加简单。例如,如果需要取消所有任务,只需调用scheduler.shutdown()即可。

  6. 适合定时任务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实现高效物联温度控制链路,确保温度调节的准确性和效率,定时链路执行使用案例,一环扣一环

主要功能和场景 柔性调温策略&#xff1a;这个类主要用于管理一个温度调节流程&#xff0c;通过不同的策略&#xff08;如策略1和策略2&#xff09;来调节温度&#xff0c;确保设备或环境中的温度达到预设的目标。 紧急停止机制&#xff1a;在流程执行过程中&#xff0c;如果需…...

yolov8部署资料

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

迅为RK3588开发板支持LVDS信号,标准 HDMI信号,IMIPI信号

性能强--iTOP-3588开发板采用瑞芯微RK3588处理器&#xff0c;是全新一代ALoT高端应用芯片&#xff0c;采用8nm LP制程&#xff0c;搭载八核64位CPU&#xff0c;四核Cortex-A76和四核Cortex-A55架构&#xff0c;主频高达2.4GHZ&#xff0c;8GB内存&#xff0c;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分析:品牌如何评估带货效果

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

硬件实用技巧:电容精度和常用容值表

若该文为原创文章&#xff0c;转载请注明原文出处 本文章博客地址&#xff1a;https://hpzwl.blog.csdn.net/article/details/140009042 长沙红胖子Qt&#xff08;长沙创微智科&#xff09;博文大全&#xff1a;开发技术集合&#xff08;包含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&#xff0c;允许网页和 Web 应用程序向用户展示一个标准化的支付界面&#xff0c;以便用户快速、方便地进行付款。这种 API 的设计目的是为了简化用户支付过程&#xff0c;提高支付转化率&#xff0c;并提供一种更加统一的支付体验。 支持…...

【杂记-浅谈EBGP外部边界网关协议、IBGP内部边界网关协议】

一、EBGP概述 EBGP&#xff0c;External Border Gateway Protocol&#xff0c;即外部边界网关协议&#xff0c;EBGP主要用于在不同自治系统&#xff08;AS&#xff09;之间交换路由信息&#xff0c;每个AS都有一个独特的AS号码&#xff0c;用于区分不同的自治系统。EBGP通过AS…...

基于Java的宠物领养管理系统【附源码】

摘 要 近些年来&#xff0c;随着科技的飞速发展&#xff0c;互联网的普及逐渐延伸到各行各业中&#xff0c;给人们生活带来了十分的便利&#xff0c;宠物管理系统利用计算机网络实现信息化管理&#xff0c;使整个宠物领养的发展和服务水平有显著提升。 本文拟采用IDEA开发工具…...

Grafana 对接 Zabbix 数据源API错误

介绍 主要报错为 Invalid params. Invalid parameter "/": unexpected parameter "user". 主要原因为Zabbix 6.4.0以上的版本更新了API&#xff0c;导致Grafana的数据源插件不兼容。 解决方案 更新到最新的Grafana 和 grafana-zabbix 插件即可。&#x…...

Spring Boot与Apache Kafka的深度集成

Spring Boot与Apache Kafka的深度集成 大家好&#xff0c;我是免费搭建查券返利机器人省钱赚佣金就用微赚淘客系统3.0的小编&#xff0c;也是冬天不穿秋裤&#xff0c;天冷也要风度的程序猿&#xff01;今天我们将探讨如何在Spring Boot应用中实现与Apache Kafka的深度集成&am…...

07 Pytoch Module

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

Isaac Sim 9 物理(1)

使用Python USD API 来实现 Physics 。 以下内容中&#xff0c;大部分 Python 代码可以在 Physics Python 演示脚本文件中找到&#xff0c;本文仅作为个人学习笔记。 一.设置 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&#xff0c;北京大学PKU-DAIR实习生—余昭辰的Talk已经准时在TechBeat人工智能社区开播&#xff01; 他与大家分享的主题是: “从多模态理解到生成 - 从LLM到Diffusion Model”&#xff0c;在本次Talk…...

数据中台高频面试题及参考答案(持续更新)

做大数据开发的,个人感觉招人最多的是是数据中台和数据仓库领域的。所以对数据中台、数据仓库相关的面试题要熟悉。 什么是数据中台?它与传统数据仓库的区别是什么? 数据中台是一种企业级的数据管理和分析平台,旨在通过集成、处理和分析来自企业内外部的大量多样化的数据…...

腾讯云CVM,CentOS8系统下部署Java-Web项目步骤详解

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

Jenkins 创建流水线任务

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

单总线协议耗材认证加密芯片ALPU-P

这是一款采用随机变量交换系统的认证加密芯片。ALPU-P与系统MCU以密码方式通信&#xff0c;MCU在诸如系统启动等关键场合检测ALPU-P加密芯片。所以即使盗版系统复制了PCB、内核甚至存储器中的固件&#xff0c;但若缺少ALPU-P芯片&#xff0c;该系统仍然无法工作。 加密芯片是对…...

7.4.分块查找

一.分块查找的算法思想&#xff1a; 1.实例&#xff1a; 以上述图片的顺序表为例&#xff0c; 该顺序表的数据元素从整体来看是乱序的&#xff0c;但如果把这些数据元素分成一块一块的小区间&#xff0c; 第一个区间[0,1]索引上的数据元素都是小于等于10的&#xff0c; 第二…...

Debian系统简介

目录 Debian系统介绍 Debian版本介绍 Debian软件源介绍 软件包管理工具dpkg dpkg核心指令详解 安装软件包 卸载软件包 查询软件包状态 验证软件包完整性 手动处理依赖关系 dpkg vs apt Debian系统介绍 Debian 和 Ubuntu 都是基于 Debian内核 的 Linux 发行版&#xff…...

STM32F4基本定时器使用和原理详解

STM32F4基本定时器使用和原理详解 前言如何确定定时器挂载在哪条时钟线上配置及使用方法参数配置PrescalerCounter ModeCounter Periodauto-reload preloadTrigger Event Selection 中断配置生成的代码及使用方法初始化代码基本定时器触发DCA或者ADC的代码讲解中断代码定时启动…...

IoT/HCIP实验-3/LiteOS操作系统内核实验(任务、内存、信号量、CMSIS..)

文章目录 概述HelloWorld 工程C/C配置编译器主配置Makefile脚本烧录器主配置运行结果程序调用栈 任务管理实验实验结果osal 系统适配层osal_task_create 其他实验实验源码内存管理实验互斥锁实验信号量实验 CMISIS接口实验还是得JlINKCMSIS 简介LiteOS->CMSIS任务间消息交互…...

Java线上CPU飙高问题排查全指南

一、引言 在Java应用的线上运行环境中&#xff0c;CPU飙高是一个常见且棘手的性能问题。当系统出现CPU飙高时&#xff0c;通常会导致应用响应缓慢&#xff0c;甚至服务不可用&#xff0c;严重影响用户体验和业务运行。因此&#xff0c;掌握一套科学有效的CPU飙高问题排查方法&…...

LangChain知识库管理后端接口:数据库操作详解—— 构建本地知识库系统的基础《二》

这段 Python 代码是一个完整的 知识库数据库操作模块&#xff0c;用于对本地知识库系统中的知识库进行增删改查&#xff08;CRUD&#xff09;操作。它基于 SQLAlchemy ORM 框架 和一个自定义的装饰器 with_session 实现数据库会话管理。 &#x1f4d8; 一、整体功能概述 该模块…...

三分算法与DeepSeek辅助证明是单峰函数

前置 单峰函数有唯一的最大值&#xff0c;最大值左侧的数值严格单调递增&#xff0c;最大值右侧的数值严格单调递减。 单谷函数有唯一的最小值&#xff0c;最小值左侧的数值严格单调递减&#xff0c;最小值右侧的数值严格单调递增。 三分的本质 三分和二分一样都是通过不断缩…...

【Android】Android 开发 ADB 常用指令

查看当前连接的设备 adb devices 连接设备 adb connect 设备IP 断开已连接的设备 adb disconnect 设备IP 安装应用 adb install 安装包的路径 卸载应用 adb uninstall 应用包名 查看已安装的应用包名 adb shell pm list packages 查看已安装的第三方应用包名 adb shell pm list…...

零知开源——STM32F103RBT6驱动 ICM20948 九轴传感器及 vofa + 上位机可视化教程

STM32F1 本教程使用零知标准板&#xff08;STM32F103RBT6&#xff09;通过I2C驱动ICM20948九轴传感器&#xff0c;实现姿态解算&#xff0c;并通过串口将数据实时发送至VOFA上位机进行3D可视化。代码基于开源库修改优化&#xff0c;适合嵌入式及物联网开发者。在基础驱动上新增…...

DeepSeek源码深度解析 × 华为仓颉语言编程精粹——从MoE架构到全场景开发生态

前言 在人工智能技术飞速发展的今天&#xff0c;深度学习与大模型技术已成为推动行业变革的核心驱动力&#xff0c;而高效、灵活的开发工具与编程语言则为技术创新提供了重要支撑。本书以两大前沿技术领域为核心&#xff0c;系统性地呈现了两部深度技术著作的精华&#xff1a;…...