延时性(过期/超时)和周期性的定时任务的实现方式

延时性(过期/超时)和周期性的定时任务的实现方式

  • 一、延时性的定时任务(例如订单超时30分钟后自动取消该订单)
    • 1.使用DelayQueue实现任务即将到期提醒功能(非分布式)
    • 2.使用Redis实现任务即将到期提醒功能(分布式)
      • 方式一:ZSet 实现方式
      • 方式二:键空间通知
  • 二、周期性的定时任务(例如每周五 23:59:59 例行执行巡视任务)
    • 1.开启定时任务
    • 2.添加定时任务

一、延时性的定时任务(例如订单超时30分钟后自动取消该订单)

任务在发出后的一定时间后进行逻辑处理,例如订单超时30分钟后自动取消该订单

1.使用DelayQueue实现任务即将到期提醒功能(非分布式)

import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import java.util.concurrent.DelayQueue;
import java.util.concurrent.Delayed;
import java.util.concurrent.TimeUnit;@Component
@Slf4j
public class TaskTimeoutReminderUtil {private static DelayQueue<TimeoutTask> delayQueue = new DelayQueue<>();static class TimeoutTask implements Delayed {private String taskId;private long expireTime;public TimeoutTask(String taskId, long timeoutMillis) {this.taskId = taskId;this.expireTime = System.currentTimeMillis() + timeoutMillis;}@Overridepublic long getDelay(TimeUnit unit) {return unit.convert(expireTime - System.currentTimeMillis(), TimeUnit.MILLISECONDS);}@Overridepublic int compareTo(Delayed other) {if (other instanceof TimeoutTask) {TimeoutTask that = (TimeoutTask) other;return Long.compare(this.expireTime, that.expireTime);}return 0;}public String getTaskId() {return taskId;}}// 添加订单到延迟队列public static void addOrder(String taskId, long timeoutMillis) {delayQueue.offer(new TimeoutTask(taskId, timeoutMillis));}@PostConstructpublic void init() {for (int i = 0; i < 10; i++) {TaskTimeoutReminderUtil.addOrder("task"+i, 1000*i);}// 启动一个单独的线程来处理超时任务new Thread(() -> {while (true) {try {TimeoutTask task = delayQueue.take();log.info("任务{}即将到期,请尽快处理", task.getTaskId());} catch (InterruptedException e) {log.error("处理超时任务时发生异常");e.printStackTrace();}}}).start();}
}

2.使用Redis实现任务即将到期提醒功能(分布式)

方式一:ZSet 实现方式

通过 ZSet 实现定时任务的思路是,将定时任务存放到 ZSet 集合中,并且将过期时间存储到 ZSet 的 Score 字段中,然后通过一个无线循环来判断当前时间内是否有需要执行的定时任务,如果有则进行执行,具体实现代码如下:

import redis.clients.jedis.Jedis;
import utils.JedisUtils;
import java.time.Instant;
import java.util.Set;public class DelayQueueExample {// zset keyprivate static final String _KEY = "myTaskQueue";public static void main(String[] args) throws InterruptedException {Jedis jedis = JedisUtils.getJedis();// 30s 后执行long delayTime = Instant.now().plusSeconds(30).getEpochSecond();jedis.zadd(_KEY, delayTime, "order_1");// 继续添加测试数据jedis.zadd(_KEY, Instant.now().plusSeconds(2).getEpochSecond(), "order_2");jedis.zadd(_KEY, Instant.now().plusSeconds(2).getEpochSecond(), "order_3");jedis.zadd(_KEY, Instant.now().plusSeconds(7).getEpochSecond(), "order_4");jedis.zadd(_KEY, Instant.now().plusSeconds(10).getEpochSecond(), "order_5");// 开启定时任务队列doDelayQueue(jedis);}/*** 定时任务队列消费* @param jedis Redis 客户端*/public static void doDelayQueue(Jedis jedis) throws InterruptedException {while (true) {// 当前时间Instant nowInstant = Instant.now();long lastSecond = nowInstant.plusSeconds(-1).getEpochSecond(); // 上一秒时间long nowSecond = nowInstant.getEpochSecond();// 查询当前时间的所有任务Set<String> data = jedis.zrangeByScore(_KEY, lastSecond, nowSecond);for (String item : data) {// 消费任务System.out.println("消费:" + item);}// 删除已经执行的任务jedis.zremrangeByScore(_KEY, lastSecond, nowSecond);Thread.sleep(1000); // 每秒查询一次}}
}

方式二:键空间通知

我们可以通过 Redis 的键空间通知来实现定时任务,它的实现思路是给所有的定时任务设置一个过期时间,等到了过期之后,我们通过订阅过期消息就能感知到定时任务需要被执行了,此时我们执行定时任务即可。

默认情况下 Redis 是不开启键空间通知的,需要我们通过 config set notify-keyspace-events Ex 的命令手动开启(或在配置文件中修改),开启之后定时任务的代码如下:

import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPubSub;
import utils.JedisUtils;public class TaskExample {public static final String _TOPIC = "__keyevent@0__:expired"; // 订阅频道名称public static void main(String[] args) {Jedis jedis = JedisUtils.getJedis();// 执行定时任务doTask(jedis);}/*** 订阅过期消息,执行定时任务* @param jedis Redis 客户端*/public static void doTask(Jedis jedis) {// 订阅过期消息jedis.psubscribe(new JedisPubSub() {@Overridepublic void onPMessage(String pattern, String channel, String message) {// 接收到消息,执行定时任务System.out.println("收到消息:" + message);}}, _TOPIC);}
}

二、周期性的定时任务(例如每周五 23:59:59 例行执行巡视任务)

在某个时间点周期性执行任务,例如每周五 23:59:59 例行执行巡视任务
参考:https://blog.csdn.net/HackAzrael/article/details/122194645

1.开启定时任务

开启定时任务只需要在 Spring Boot 的启动类上声明 @EnableScheduling 即可,实现代码如下:

@SpringBootApplication
@EnableScheduling // 开启定时任务
public class DemoApplication {// do someing
}

2.添加定时任务

定时任务的添加只需要使用 @Scheduled 注解标注即可,如果有多个定时任务可以创建多个 @Scheduled 注解标注的方法,示例代码如下:

import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;@Component // 把此类托管给 Spring,不能省略
public class TaskUtils {// 添加定时任务@Scheduled(cron = "59 59 23 0 0 5") // cron 表达式,每周五 23:59:59 执行public void doTask(){System.out.println("我是定时任务~");}
}

Cron 表达式介绍
Spring Task 的实现需要使用 cron 表达式来声明执行的频率和规则,cron 表达式是由 6 位或者 7 位组成的(最后一位可以省略),每位之间以空格分隔,每位从左到右代表的含义如下:
在这里插入图片描述
在这里插入图片描述
cron 表达式在线生成地址:https://cron.qqe2.com/

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

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

相关文章

探索Web3工具:正确使用区块链平台工具的秘诀

在当今日新月异的数字时代&#xff0c;区块链技术正以惊人的速度改变着我们的生活和工作方式。尤其对于那些想要踏入区块链世界的人来说&#xff0c;正确使用区块链平台工具至关重要。本文将向您介绍一些关键的Web3工具&#xff0c;并以TestnetX.com为例&#xff0c;展示如何利…

数字化转型推动生物技术企业增长—纷享销客与集萃药康共探新动力

上周&#xff0c;在南京锦创书城&#xff0c;一场主题为“生物技术企业增长新动力&#xff1a;以客户为中心的数字化转型与创新”的研讨会圆满落幕。此次活动由纷享销客江苏分公司联合江苏集萃药康生物科技股份有限公司共同举办&#xff0c;吸引了众多生物技术领域企业的负责人…

斑消宝六周年大动作,斑小将将再迎高光时刻

如今&#xff0c;周年庆典已经成为众多品牌展示自身实力与影响力的重要舞台。这不仅仅是一个简单的庆祝活动&#xff0c;更是一次向外界展示品牌发展历程、未来规划以及团结合作伙伴的绝佳机会。在这样的背景下&#xff0c;广州斑消宝化妆品有限公司将打造别具一格的盛典&#…

npm安装依赖报错npm ERR! code ENOTFOUNDnpm ERR! syscall getaddrinfo

npm安装依赖报错 今天在学习vue的时候&#xff0c;在使用npm install vue -g来安装一个局部的vue时候&#xff0c;报出如下错误&#xff1a; npm ERR! code CERT_HAS_EXPIRED npm ERR! errno CERT_HAS_EXPIRED npm ERR! request to https://registry.npm.taobao.org/vue faile…

iphone内存满了开不了机怎么办?白苹果解决办法分享!

虽然苹果手机在使用时比较顺畅&#xff0c;但是手机用久了&#xff0c;照片、视频等资料累积过多&#xff0c;也难免会导致内存不足&#xff0c;出现无法开机卡在开机界面白苹果的情况。 内存不足导致iPhone白苹果的问题很常见&#xff0c;可以说是苹果最常见的故障之一。接下来…

【学习笔记】Windows GDI绘图(九)Graphics详解(上)

文章目录 Graphics 定义创建Graphics对象的方法通过Graphics绘制不同的形状、线条、图像和文字等通过Graphics操作对象坐标 Graphics属性Clip(裁切/绘制区域)ClipBounds获取裁切区域矩形范围CompositiongMode合成方式CompositingQuality渲染质量DpiX和DpiY 水平、垂直分辨率Int…

C++ 逻辑运算

一 逻辑运算 2 逻辑运算符 逻辑表达式 四 逻辑表达式 五 逻辑运算符的优先级 六 注意事项 注意 总结

JVM学习-字节码指令集(四)

异常处理指令 抛出异常指令 athrow指令&#xff1a;在Java程序中显示抛出异常的操作(throw语句)都是由athrow指令来实现除了throw语句显示抛出异常情况之外&#xff0c;JVM规范还规定了许多运行时异常会在其他Java虚拟机指令检测到异常状况时自动抛出&#xff0c;在之前介绍的…

vcruntime140_1.dll在哪个文件夹?详细修复vcruntime140_1.dll缺失的方法

vcruntime140_1.dll文件是什么&#xff1f;相信很多人都对它很陌生吧&#xff1f;毕竟大部分人对于dll文件还是了解得太少了&#xff0c;当突发情况出现vcruntime140_1.dll文件丢失&#xff1f;你要怎么办&#xff1f;不要担心&#xff0c;下面我们就来给大家详细的讲解一下修复…

GPT-4o:人工智能技术的新巅峰

人不走空 &#x1f308;个人主页&#xff1a;人不走空 &#x1f496;系列专栏&#xff1a;算法专题 ⏰诗词歌赋&#xff1a;斯是陋室&#xff0c;惟吾德馨 目录 &#x1f308;个人主页&#xff1a;人不走空 &#x1f496;系列专栏&#xff1a;算法专题 ⏰诗词歌…

Maven简介和快速入门

1.1Maven介绍 Maven – Introduction (apache.org) Maven就是一个软件&#xff0c;掌握软件安装、配置、以及基本功能&#xff08;项目构建、依赖管理&#xff09;。 1.2Maven主要作用 1.依赖管理&#xff1a; Maven 可以管理项目的依赖&#xff0c;包括自动下载所需依赖库、…

AI图书推荐:使用GitHub Copilot和ChatGPT辅助的Python编程

使用Python编写计算机程序变得更加简单了&#xff01;使用像GitHub Copilot和ChatGPT这样的AI辅助编码工具&#xff0c;将你的想法快速转化为应用程序。人工智能已经改变了我们编写计算机程序的方式。有了像Copilot和ChatGPT这样的工具&#xff0c;你可以用简单的英语描述你想要…

Windows环境安装redis

1、下载redis https://github.com/tporadowski/redis/releases 2、解压 .zip 3、更改文件名 更改文件名称为&#xff1a;redis 4、将本地解压后的redis&#xff0c;作为本地服务器下的应用服务 从redis文件路径下&#xff0c;执行cmd .\redis-server --service-install re…

设计模式——工厂三兄弟之抽象工厂

1.业务需求 ​ 大家好&#xff0c;我是菠菜啊。今天给大家介绍工厂三兄弟最后一个兄弟——抽象工厂。老规矩&#xff0c;在介绍这期抽象工厂模式前&#xff0c;我们先来看看这样的需求&#xff1a;现在有俩个制造工厂&#xff0c;都要生产冰箱产品&#xff0c;并且客户在使用冰…

Java 内存泄露风险

目录 内存泄露的定义 潜在的内存泄露场景 未关闭的资源类 未正确实现 equals() 和 hashCode() 非静态内部类 重写了 finalize() 的类 针对长字符串调用 String.intern() ThreadLocal 的误用 类的静态变量 虽然 Java 程序员不用像 C、C 程序员那样时刻关注内存的使用情…

蚂蚁技术日首次开放,精彩看点分享

每年的 5 月 27 日&#xff0c;是蚂蚁的技术日&#xff0c;用来鼓励蚂蚁技术人保持敬畏和创新之心&#xff0c;到今天&#xff0c;第九届“527 蚂蚁技术日”已发展成为技术周&#xff0c;成为蚂蚁技术人的嘉年华。 2015 年 5 月 27 日&#xff0c;因为光纤被挖断&#xff0c;全…

国产身份域管架构图集合(信创政策AD域替换必看)

几类典型架构 双机架构 单点单机房 集群架构 多点单机房 两地三中心架构 多点多机房 多地分布式架构 多点多机房 全栈信创方案架构&#xff0c;欢迎探讨交流~

React useContext源码分析

React 框架中 useContext Hook 用于数据的传递&#xff0c;组件的数据传递有几种方式&#xff0c;通过 props、状态管理 和 useContext。本文将讲述useContext 在 React 是如何工作的&#xff0c;创建一个简单的 Context 例子并根据源码进行 Debug&#xff1a; 创建 context …

剖析【C++】——类和对象(下篇)——超详解——小白篇

目录 1.再谈构造函数 1.1 构造函数体赋值 1.2 初始化列表 1.3 explicit 关键字 2. Static成员 2.1 概念 2.2 特性 3. 友元 3.1 友元函数 3.2 友元类 3.3总结&#xff1a; 4. 内部类 1.概念 2.特性 示例代码&#xff1a; 代码分析 3.总结 5.再次理解类和对象 …

MySQL各种锁

目录 1. 从粒度上区分锁 1.1 全局锁&#xff08;第一粒度&#xff09; 1.2 表级锁&#xff08;第二粒度&#xff09; 1.3 行锁&#xff08;第三最小粒度&#xff09; 2 从模式上区分锁 2.1 什么是乐观锁 2.2 什么是悲观锁 2.3 意向共享锁和意向排他锁 2.4 临键锁和记录…