Springboot自带注解@Scheduled实现定时任务

news/2024/11/27 9:45:55/

基于@Scheduled注解实现简单定时任务

原理

Spring Boot 提供了@Scheduled注解,通过在方法上添加此注解,可以方便地将方法配置为定时任务。在应用启动时,Spring 会自动扫描带有@Scheduled注解的方法,并根据注解中的参数来确定任务的执行时间。这些参数可以使用cron表达式、固定延迟(fixedDelay)或者固定速率(fixedRate)等来指定任务执行的时间规则。

步骤

创建定时任务

创建一个 Spring 管理的Bean类,在类中定义需要定时执行的方法。例如:

java">import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;@Component
public class SimpleScheduledTask {@Scheduled(fixedRate = 5000) // 每隔5秒执行一次任务public void executeTask() {System.out.println("定时任务执行了");}
}

配置定时任务(在 Spring Boot 主类或配置类中开启定时任务支持) 

java">import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableScheduling;@SpringBootApplication
@EnableScheduling
public class Application {public static void main(String[] args) {SpringApplication.run(Application.class, args);}
}

时间参数设置方式 

cron表达式 

cron表达式是一种强大的时间表达式,用于精确地指定任务执行时间。例如,@Scheduled(cron = "0 0 12 * * *")表示每天中午 12 点执行任务。cron表达式的格式为:秒 分 时 日 月 周 年(年可省略),每个字段可以使用通配符(*)、数字范围(如1 - 5)、逗号分隔的列表(如1,3,5)等来表示不同的时间规则。

 固定延迟(fixedDelay)

fixedDelay参数指定的时间间隔是在前一个任务执行完成后,等待指定的时间再执行下一个任务。例如,@Scheduled(fixedDelay = 3000)表示当前任务执行完成后,等待 3 秒再执行下一个任务。

固定速率(fixedRate 

fixedRate参数指定的时间间隔是从任务开始执行的时间点开始计算,每隔固定的时间就执行一次任务,不管前一个任务是否已经执行完成。例如,@Scheduled(fixedRate = 2000)表示每隔 2 秒就执行一次任务,即使前一个任务还没有执行完。

扩展 

使用ScheduledExecutorService实现复杂定时任务(更灵活的方式) 

原理 

ScheduledExecutorService是 Java 提供的用于在后台执行定时任务或周期性任务的接口,它提供了更灵活的任务调度方式,相比@Scheduled注解可以更好地控制任务的并发执行、动态任务添加和删除等操作。Spring Boot 也可以很方便地整合ScheduledExecutorService来实现定时任务

步骤 

创建定时任务 
java">import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;import org.springframework.stereotype.Component;@Component
public class ComplexScheduledTask {private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);public void startTask() {// 延迟1秒后执行任务,之后每隔3秒执行一次scheduler.scheduleAtFixedRate(() -> {System.out.println("复杂定时任务执行了");}, 1, 3, TimeUnit.SECONDS);}
}
在合适的地方启动定时任务(如在应用启动后) 

可以在 Spring Boot 的启动类的main方法中,或者通过实现ApplicationListener<ContextRefreshedEvent>接口在容器初始化完成后启动定时任务。以下是通过ApplicationListener接口启动定时任务的示例:

java">import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.stereotype.Component;@Component
public class TaskStarter implements ApplicationListener<ContextRefreshedEvent> {private final ComplexScheduledTask complexScheduledTask;public TaskStarter(ComplexScheduledTask complexScheduledTask) {this.complexScheduledTask = complexScheduledTask;}@Overridepublic void onApplicationEvent(ContextRefreshedEvent event) {if (event.getApplicationContext().getParent() == null) {// 这是根容器,在这里启动定时任务complexScheduledTask.startTask();}}
}

优势和注意事项 

 优势

并发控制更好:可以通过ScheduledExecutorService的线程池配置来控制任务的并发执行,例如设置线程池大小,适用于有多个定时任务需要并发执行或者对任务执行的顺序和并发情况有特殊要求的场景。

动态任务管理:能够方便地在运行时动态添加、删除或修改定时任务,例如根据用户的配置或者系统的运行状态来调整定时任务的执行计划,这在一些复杂的业务场景中非常有用。

注意事项 

需要注意资源管理,特别是在长时间运行的定时任务中,要确保任务不会出现内存泄漏、资源占用过多等问题。例如,在任务执行过程中如果涉及到数据库连接、文件操作等资源的使用,需要合理地进行资源的获取和释放。

结合消息队列实现分布式定时任务(适用于分布式系统) 

原理 

在分布式系统中,单纯的本地定时任务可能无法满足需求。通过结合消息队列(如 RabbitMQ、Kafka 等)可以实现分布式定时任务。基本思路是将定时任务的触发信息(如任务执行时间、任务参数等)发送到消息队列中,然后多个消费者(可以是不同的服务实例)从消息队列中获取任务信息并执行任务,这样可以实现任务的分布式调度和执行。

步骤(以 RabbitMQ 为例)

 配置消息队列和生产者(用于发送定时任务消息)

首先需要在 Spring Boot 项目中配置 RabbitMQ,包括添加依赖、配置连接信息等。然后创建一个生产者来发送定时任务相关的消息。例如:

java">import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;@Component
public class DistributedTaskProducer {private final RabbitTemplate rabbitTemplate;@Autowiredpublic DistributedTaskProducer(RabbitTemplate rabbitTemplate) {this.rabbitTemplate = rabbitTemplate;}@Scheduled(cron = "0 0 12 * * *") // 每天中午12点发送定时任务消息public void sendTaskMessage() {String taskMessage = "这是一个分布式定时任务消息";rabbitTemplate.convertAndSend("task_exchange", "task_routing_key", taskMessage);}
}
配置消费者(用于接收并执行定时任务

配置消费者来接收消息队列中的任务消息并执行任务逻辑。例如:

java">import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;@Component
public class DistributedTaskConsumer {@RabbitListener(queues = "task_queue")public void receiveAndExecuteTask(String taskMessage) {System.out.println("接收到分布式定时任务消息并执行:" + taskMessage);// 在这里添加具体的任务执行逻辑,如调用其他服务、处理数据等}
}

 注意事项

需要确保消息队列的可靠性和稳定性,包括消息的持久化、消息的确认机制等,以防止任务消息丢失或者重复执行。例如,在 RabbitMQ 中,可以通过设置消息的持久化属性和合理使用消息确认机制(如手动确认消息)来提高系统的可靠性。

分布式定时任务的调度和执行可能会涉及到时间同步、任务幂等性等问题。例如,不同的服务实例的时间可能存在差异,需要考虑这种差异对定时任务执行时间的影响;同时,为了防止任务在分布式环境下因为网络等原因重复执行,需要在任务执行逻辑中添加幂等性处理机制,如通过记录任务执行状态等方式来确保任务只执行一次。


http://www.ppmy.cn/news/1550315.html

相关文章

c++:面向对象三大特性--继承

面向对象三大特性--继承 一、继承的概念及定义&#xff08;一&#xff09;概念&#xff08;二&#xff09;继承格式1、继承方式2、格式写法3、派生类继承后访问方式的变化 &#xff08;三&#xff09;普通类继承&#xff08;四&#xff09;类模板继承 二、基类和派生类的转换&a…

(五)Ubuntu22.04+Stable-Diffusion-webui AI绘画 模型转换插件安装及其使用

一、说明 这是秋叶大佬开发的一个模型转换插件&#xff0c;秋叶整合包中自带。如果你的 Stable Diffusion WebUI 中没有这个插件&#xff0c;请使用下面这个地址安装&#xff0c;安装完成之后别忘了重启 WebUI。 模型转换插件 https://github.com/Akegarasu/sd-webui-model-c…

深度神经网络模型压缩学习笔记二:离线量化算法和工具、实现原理和细节

文章目录 一、离线量化基础概念二、离线量化难点三、离线量化算法介绍四、离线量化工具介绍五、离线量化工具整体设计结构六、离线量化工具代码解读七、实践&#xff1a;Dipoorlet量化MobileNet 一、离线量化基础概念 二、离线量化难点 三、离线量化算法介绍 四、离线量化工…

低速接口项目之串口Uart开发(二)——FIFO实现串口数据的收发回环测试

本节目录 一、设计思路 二、loop环回模块 三、仿真模块 四、仿真验证 五、上板验证 六、往期文章链接本节内容 一、设计思路 串口数据的收发回环测试&#xff0c;最简单的硬件测试是把Tx和Rx连接在一起&#xff0c;然后上位机进行发送和接收测试&#xff0c;但是需要考虑到串…

PyQt5:Python GUI开发的超级英雄

PyQt5&#xff1a;Python GUI开发的超级英雄 &#x1f680; 引言&#xff1a; 你是否厌倦了编写枯燥的命令行程序&#xff1f;想要让你的Python项目拥有炫酷的用户界面吗&#xff1f;今天&#xff0c;我们就来聊聊Python GUI开发的超级英雄——PyQt5&#xff01;&#x1f31f;…

C++设计模式之组合模式中适用缓存机制提高遍历与查找速度

在组合设计模式中&#xff0c;为了提高反复遍历和查找的速度&#xff0c;可以引入缓存机制。缓存机制可以通过存储已经遍历过的子组件或计算过的结果来减少重复操作的开销。以下是一个示例&#xff0c;展示了如何在组合模式中使用缓存机制来提高性能。 示例&#xff1a;组合设…

网络--传输层协议--UDP

传输层作用:负责数据能够从发送端传输到接收端。 1、再谈端口号 端口号标识了一个主机上进行通信的不同的应用程序。 1.1、端口号划分范围 0 - 1023 : 知名端口号,HTTP、FTP、SSH等这些广为使用的应用层协议,他们的端口号都是固定的。 10234 - 65536:操作系统动态分配的…

旋转磁体产生的场 - 实验视频资源下载

先发几个视频&#xff0c;是2019年所作的实验内容 更多视频&#xff0c;到某宝找我吧。注意&#xff1a;是收费的。 20190312-180244-旋转磁体产生的场造成激光功率减小 https://download.csdn.net/download/u014161757/90038058 20190313-090956-旋转磁体产生的场对真空介电…