Delayed 延时任务

延时任务与定时任务的区别

延时任务,可以理解为定时任务的一种,但是他们是有区别的。
延时任务:将程序代码延时执行,执行完毕,即为结束。
定时任务:周期性执行任务。代码执行完毕后,并不意味着结束,会根据定时的周期时间,继续下次的执行。

如何做定时任务?

之前做过一期的博客:Redis做定时任务
但是是有错误的。我把redis的那个空间变动通知当成定时了!其实他应该算是延时。。。。
那如何做呢?

  • java自带的延时队列
  • redis空间变动通知
  • 可使用定时任务的那种任务调度器做:设置好时间,执行一次,然后关闭。
  • ……
实操

新的项目新的需求,一个物联网那个项目。设备爆出警报来后,用户可以设置忽略误报,在多少时间内,不在提示这个错误。
对应到数据上,就是报警数据的[字段:处理状态]修改为已处理,就查不到报警信息了。但是忽略时间一到,状态会自动改回未处理

刚开始,我是想使用Redis来做的,但是想使用redis,就必须修改配置文件,服务器不在我们手里,修改不了,这个方案被pass掉了。
然后,我使用项目中自带的任务调度器xxl-job(开源的任务调度器,跟Quartz一样的东西),自己计算cron表达式,添加任务,启动任务,然后执行修改方法,关闭任务。但是么,最后。。。被领导臭骂了一顿。说是用延时队列来做。。。

创建操作类

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.jetbrains.annotations.NotNull;import java.util.List;
import java.util.concurrent.Delayed;
import java.util.concurrent.TimeUnit;@Data
@NoArgsConstructor
@AllArgsConstructor
public class DelayedAlarm implements Delayed {/*** 过期时间。这个时间一定是一个Date类型转成的*/private Long expireTime;/*** 集合ID*/private List<String> alarmIds;/*** 是否过期。小于等于0的,表示过期,大于0的,表示未过期,其差值表示还有多少时间过期。* 这个我踩了一个大坑。我写的代码为啥就是不会延时执行?* 因为这个方法表示还有多少时间过期,一定是过期时间减去当前时间,还剩下多少时间。* 而我直接unit.convert(expireTime,TimeUnit.MILLISECONDS)了,* 因为只是做了一下时间的转换,每次java调用这个方法判断还有多长时间过期,一直是这个数,所以他就一直延时。。。。* @param unit 时间的单位* @return 返回排序结果*/@Overridepublic long getDelay(@NotNull TimeUnit unit) {return unit.convert(expireTime - System.currentTimeMillis(), TimeUnit.MILLISECONDS);}/*** 排序方法。用于排序,因为放进来的对象,根据延时时间的大小,不一定是排在后面的,,有可能是排在前面的。* @param o 刚加入对象* @return 返回排序结果*/@Overridepublic int compareTo(@NotNull Delayed o) {return (int) (this.getDelay(TimeUnit.MILLISECONDS) - o.getDelay(TimeUnit.MILLISECONDS));}
}
业务调用
//省略不重要的导入
public class AlarmServiceImpl {//省略其他不重要的注入。private final DelayQueue<DelayedAlarm> DELAY_QUEUE = new DelayQueue<>();@PostConstructpublic void updateAlarmStatusQueue() {//因为是本地缓存的队列,重启服务会丢失,需要重新查库,重新添加队列List<AlarmInfo> list = alarmInfoMapper.getIgnoreAlarmList();list.forEach(entity -> {long timeDiff = System.currentTimeMillis() - entity.getAlarmStartTime().getTime();long expireTime = entity.getIgnoreTime() * 1000L;if (expireTime > timeDiff) {//当前忽略时间>时间差expireTime = expireTime - timeDiff;} else {expireTime = 0;}DELAY_QUEUE.put(new DelayedAlarm(expireTime, Arrays.asList(entity.getId())));});//这个地方。等价于 ThreadPoolExecutor executor=Executors.newSingleThreadExecutor()。//阿里巴巴代码扫描,总是飘黄,我给改了一下。。ThreadPoolExecutor executor = new ThreadPoolExecutor(1, 1,0L, TimeUnit.MILLISECONDS,new LinkedBlockingQueue<Runnable>(),new DefaultThreadFactory("alarm_delaye_queue"));executor.execute(new Thread(() -> {while (true) {try {DelayedAlarm take = DELAY_QUEUE.take();//获取id集合,执行业务逻辑this.updateAlarmStatus(take.getAlarmIds());log.info("延时执行队列成功");} catch (Exception e) {//注意:一定要捕获异常,否则出现异常while循环就结束了。log.error("延时执行队列失败", e);}}}));}/*** 忽略误报时间到了,自动修改警报信息状态:已处理-->未处理* @param alarmIds 警报信息ID 集合* @return*/public void updateAlarmStatus(List<String> alarmIds) {List<AlarmInfo> list = new ArrayList<>();alarmIds.forEach(id -> {//开始更新警报信息状态list.add(new AlarmInfo().setId(id).setStatus(UN_DISPOSED.getType()).setLastModifyUserId(userUtil.getUserId()));});//集成了mybaits-plus 插件,我代码给删除了,大家用的时候需要自己写Mapperthis.updateBatchById(list);log.info("延时执行修改报警信息状态成功:{}",JSONObject.toJSONString(alarmIds));}/*** 将当前的忽略误报信息添加延时队列* @param ids 警报信息ID 集合* @param expireTime 过期时间*/public void handleIgnoreAlarm(List<String> ids,Date expireTime) {//省略不重要的业务。。。。//添加队列DELAY_QUEUE.put(new DelayedAlarm(expireTime.getTime(), ids));}
}

最后看一下执行结果
在这里插入图片描述

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

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

相关文章

零基础安装分布式数据服务注册系统

一、先安装VM虚拟机&#xff0c;安装最新的ubuntu22系统&#xff0c; 先安装mysql&#xff0c; sudo apt install mysql-server sudo mysql_secure_installation 根据自己需求选择 密码安全级别时&#xff0c;选择n 删除匿名用户&#xff1f;&#xff08;按y|Y表示是&…

C++实现线程安全的vector

C++实现线程安全的vector,我们需要确保在任何时候只有一个线程可以修改vector。这通常通过使用互斥锁(例如 std::mutex)来实现。以下是一个简单的实现示例: #include <vector> #include <mutex>template<typename T> class ThreadSafeVector {public:

【算法挨揍日记】day23——740. 删除并获得点数、LCR 091. 粉刷房子

740. 删除并获得点数 740. 删除并获得点数 题目描述&#xff1a; 给你一个整数数组 nums &#xff0c;你可以对它进行一些操作。 每次操作中&#xff0c;选择任意一个 nums[i] &#xff0c;删除它并获得 nums[i] 的点数。之后&#xff0c;你必须删除 所有 等于 nums[i] - 1…

PyCharm:PyCharm新建.py文件时自动带出指定内容

在pycharm中加上指定内容&#xff0c;每次新建.py文件都会自动带出指定内容 操作&#xff1a; File—Setting—Editor----File and Code Templates--Python Script 在右侧窗口中加上如下信息 # encoding: utf-8 # author: Jeffrey # file: ${NAME}.py # time: ${DATE} ${TI…

Kettle 简介

1. PDI结构简介 图 1‑1 PDI核心组件 Spoon是构建ETL Jobs和Transformations的工具。Spoon可以以拖拽的方式图形化设计&#xff0c;能够通过spoon调用专用的数据集成引擎或者集群。 Data Integration Server是一个专用的ETL Server&#xff0c;它的主要功能有&#xff1a; 功能…

2023年第十六届山东省职业院校技能大赛高职组“软件测试”赛项样题

第十六届山东省职业院校技能大赛 高职组“软件测试”赛项样题 任务一&#xff1a;功能测试&#xff08;45分&#xff09; 1、测试计划&#xff08;5分&#xff09; &#xff08;1&#xff09;任务描述 针对功能测试任务&#xff0c;划分和界定测试范围&#xff0c;分解测试…

MES集成 | 集成标准不统一?看得帆云iPaaS怎么应对

得帆信息结合自身丰富实施经验及众多实践案例&#xff0c;编写了《得帆云 AIGC低代码PaaS平台系列白皮书——MES集成应用》&#xff0c;希望能为正在使用MES产品的企业数字化转型领导者和IT人员带来一些帮助。 MES是众多大型生产制造型企业在做生产执行管理时会实施的一套系统。…

魔众文库系统 v5.6.0 DWG文件格式支持,部分数据封面显示异常,定时调度清理临时文件

魔众文库系统基于文档系统知识&#xff0c;建立平台与领域&#xff0c;打造流量、用户、付费和变现的闭环&#xff0c;帮助您更好的搭建文库系统。 魔众文库系统发布v5.6.0版本&#xff0c;新功能和Bug修复累计17项&#xff0c;DWG文件格式支持&#xff0c;部分数据封面显示异…

【ES常用查询】基于ElasticsearchRestTemplate及NativeSearchQuery的查询

包含当前es所有的查询&#xff0c; 需要什么代码直接照搬&#xff0c;改个参数就行&#xff01; 用的好请务必给我点赞&#xff01;&#xff01;&#xff01;感谢爱你们&#xff01;&#xff01;&#xff01; &#xff08;周末更 筒&#xff09; 为啥写这篇文章呢&#xff…

Pytorch torch.normal()的用法

该函数原型如下&#xff1a; normal(mean, std, *, generatorNone, outNone) 该函数返回从单独的正态分布中提取的随机数的张量&#xff0c;该正态分布的均值是mean&#xff0c;标准差是std。 用法如下&#xff1a;我们从一个标准正态分布N&#xff5e;(0,1)&#xff0c;提取…

uniapp实现下载图片到本地

uniapp实现下载图片到本地 在uniapp开发中&#xff0c;可以使用uni.downloadFile方法实现下载文件功能&#xff0c;客户端直接发起一个 HTTP GET 请求&#xff0c;返回文件的本地临时路径。 const urlPath http://192.168.0.1:8080/fileApi/logo.png uni.downloadFile({url:…

Python如何实现模板方法设计模式?什么是模板方法设计模式?Python 模板方法设计模式示例代码

什么是模板方法&#xff08;Template Method&#xff09;设计模式&#xff1f; 模板方法&#xff08;Template Method&#xff09;是一种行为型设计模式&#xff0c;它定义了一个算法的骨架&#xff0c;将一些步骤延迟到子类中实现。这种模式允许子类为一个算法的特定步骤提供…

前后端黄金组合:Django+Vue+Element UI,助你构建完美平台!

这是一篇什么文章&#xff1f; 一篇你对测试开发工作感兴趣&#xff0c;想了解系统工作逻辑的文章。 一篇是你在开始动手搭建环境前需要了解各工具原理的文章。 这是一篇你真正开始前需要查阅的文章。 本文介绍了前后端工作原理&#xff0c;前后端搭建的流程、搭建过程中需…

防御DDOS的方法是什么?

DDOS攻击是现在很常见的一种网络攻击方式&#xff0c;如果服务器遭到DDOS攻击的话会导致服务器崩溃导致企业用户信息的泄露&#xff0c;选择服务器租用&#xff0c;IDC服务器商家专业的技术人员会有哪些防范措施&#xff0c;今天小编就给大家讲一讲吧&#xff01; 1、采用高防服…

SQLMAP --TAMPER的编写

跟着师傅的文章进行学习 sqlmap之tamper脚本编写_sqlmap tamper编写-CSDN博客 这里学习一下tamper的编写 这里的tamper 其实就是多个绕过waf的插件 通过编写tamper 我们可以学会 在不同过滤下 执行sql注入 我们首先了解一下 tamper的结构 这里我们首先看一个最简单的例子…

Excel数据可视化—波士顿矩阵图【四象限图】

EXCEL系列文章目录 Excel系列文章是本人亲身经历职场之后萌发的想法&#xff0c;为什么Excel覆盖如此之广&#xff0c;几乎每个公司、学校、家庭都在使用&#xff0c;但是它深藏的宝藏功能却很少被人使用&#xff0c;PQ、BI这些功能同样适用于数据分析&#xff1b;并且在一些需…

Kubernetes(k8s)进阶

文章目录 Kubernetes进阶一、Namespace&#xff08;名称空间&#xff09;1.namespace介绍2.管理namespace查看namespace创建namespace删除namespaceyaml文件配置namespace 二、Pod&#xff08;最小基本部署单元&#xff09;1.pod介绍2.管理pod创建并运行pod查看pod信息访问pod删…

一周互联网简讯 | 本周互联网发生了啥?(第3期)

1.百度T7跳槽字节3-1&#xff0c;总包145万&#xff0c;压力太大想降级 硕士毕业工作10年&#xff0c;一百度T7大头兵发文称&#xff0c;自己最近拿到字节3-1的offer&#xff0c;年包从现有的110万涨30%到145万。但是担心去字节后因为定的职级高需要带人&#xff0c;压力会很大…

【Highway-env】IntersectionEnv代码阅读

文章目录 主要完成任务代码结构1.action space2.default_config3.reward_agent_rewards_agent_reward_reward_rewards小结 4.terminated & truncated5.reset_make_road_make_vehicles_spawn_vehicle 6.step 主要完成任务 IntersectionEnv继承自AbstractEnv,主要完成以下4个…

【django+vue】项目搭建、解决跨域访问

笔记为自我总结整理的学习笔记&#xff0c;若有错误欢迎指出哟~ 【djangovue】项目搭建、解决跨域访问 djangovue介绍vue环境准备vue框架搭建1.创建vue项目2.配置vue项目3.进入项目目录4.运行项目5.项目文件讲解6.vue的扩展库或者插件 django环境准备django框架搭建1.使用conda…