spring boot处理定时任务
【摘要】 Spring Boot 提供了多种方式来处理定时任务,以下是主要的实现方法: 1. 使用 @Scheduled 注解这是最简单的方式,适用于简单的定时任务。 基本配置启用定时任务:@SpringBootApplication@EnableScheduling // 启用定时任务public class MyApplication { public static void main(S...
Spring Boot 提供了多种方式来处理定时任务,以下是主要的实现方法:
1. 使用 @Scheduled
注解
这是最简单的方式,适用于简单的定时任务。
基本配置
- 启用定时任务:
@SpringBootApplication
@EnableScheduling // 启用定时任务
public class MyApplication {
public static void main(String[] args) {
SpringApplication.run(MyApplication.class, args);
}
}
- 创建定时任务:
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
@Component
public class ScheduledTasks {
// 每5秒执行一次
@Scheduled(fixedRate = 5000)
public void taskWithFixedRate() {
System.out.println("Fixed rate task - " + System.currentTimeMillis() / 1000);
}
// 固定延迟执行(上一次执行完成后5秒再执行)
@Scheduled(fixedDelay = 5000)
public void taskWithFixedDelay() throws InterruptedException {
Thread.sleep(1000); // 模拟任务执行时间
System.out.println("Fixed delay task - " + System.currentTimeMillis() / 1000);
}
// 使用Cron表达式(每分钟的第30秒执行)
@Scheduled(cron = "30 * * * * ?")
public void taskWithCronExpression() {
System.out.println("Cron task - " + System.currentTimeMillis() / 1000);
}
}
@Scheduled
参数说明
fixedRate
:固定速率执行,从任务开始时间计算间隔fixedDelay
:固定延迟执行,从任务结束时间计算间隔initialDelay
:初始延迟(与fixedRate或fixedDelay配合使用)cron
:使用Cron表达式定义执行时间
2. 使用 TaskScheduler
接口
提供更灵活的编程方式:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.TaskScheduler;
import org.springframework.scheduling.support.CronTrigger;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import java.time.Instant;
@Component
public class DynamicScheduledTasks {
@Autowired
private TaskScheduler taskScheduler;
@PostConstruct
public void scheduleTasks() {
// 动态添加定时任务
taskScheduler.schedule(
() -> System.out.println("Dynamic task - " + Instant.now()),
new CronTrigger("0/10 * * * * ?") // 每10秒执行一次
);
}
}
3. 使用 Quartz 框架
对于更复杂的调度需求,可以集成 Quartz:
添加依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-quartz</artifactId>
</dependency>
配置 Quartz
import org.quartz.*;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class QuartzConfig {
@Bean
public JobDetail sampleJobDetail() {
return JobBuilder.newJob(SampleJob.class)
.withIdentity("sampleJob")
.storeDurably()
.build();
}
@Bean
public Trigger sampleJobTrigger() {
SimpleScheduleBuilder scheduleBuilder = SimpleScheduleBuilder.simpleSchedule()
.withIntervalInSeconds(10)
.repeatForever();
return TriggerBuilder.newTrigger()
.forJob(sampleJobDetail())
.withIdentity("sampleTrigger")
.withSchedule(scheduleBuilder)
.build();
}
}
创建 Job 类
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
public class SampleJob implements Job {
@Override
public void execute(JobExecutionContext context) throws JobExecutionException {
System.out.println("Quartz job executed - " + System.currentTimeMillis() / 1000);
}
}
4. 动态管理定时任务
如果需要运行时动态管理定时任务:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.SchedulingConfigurer;
import org.springframework.scheduling.config.ScheduledTaskRegistrar;
import org.springframework.scheduling.support.CronTrigger;
import org.springframework.stereotype.Component;
import java.util.concurrent.atomic.AtomicBoolean;
@Component
public class DynamicScheduledTask implements SchedulingConfigurer {
@Autowired
private SomeService someService;
private final AtomicBoolean enabled = new AtomicBoolean(true);
@Override
public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
taskRegistrar.addTriggerTask(
// 任务内容
() -> {
if (enabled.get()) {
someService.doSomething();
}
},
// 触发器
triggerContext -> {
String cron = enabled.get() ? "0/5 * * * * ?" : "0 0 0 1 1 ?"; // 禁用时设为无效表达式
return new CronTrigger(cron).nextExecutionTime(triggerContext);
}
);
}
public void setEnabled(boolean enabled) {
this.enabled.set(enabled);
}
}
5. 分布式定时任务
在集群环境中,可以使用以下方案避免重复执行:
-
ShedLock:轻量级分布式锁
<dependency> <groupId>net.javacrumbs.shedlock</groupId> <artifactId>shedlock-spring</artifactId> <version>4.42.0</version> </dependency> <dependency> <groupId>net.javacrumbs.shedlock</groupId> <artifactId>shedlock-provider-jdbc-template</artifactId> <version>4.42.0</version> </dependency>
@Scheduled(cron = "0 0/15 * * * *") @SchedulerLock(name = "myScheduledTask", lockAtMostFor = "14m", lockAtLeastFor = "14m") public void myScheduledTask() { // 任务内容 }
-
Quartz + JDBC:使用数据库存储调度信息
最佳实践
- 对于简单任务,优先使用
@Scheduled
- 需要动态调度时使用
TaskScheduler
- 复杂调度需求使用 Quartz
- 集群环境考虑分布式锁或Quartz集群模式
- 避免长时间运行的任务阻塞调度线程(使用
@Async
异步执行) - 合理设置异常处理,避免任务因异常终止
常见问题解决
-
定时任务不执行:
- 检查是否添加了
@EnableScheduling
- 确保定时任务类被Spring管理(有
@Component
等注解) - 检查是否有未捕获的异常
- 检查是否添加了
-
任务执行时间过长影响后续执行:
- 使用
@Async
异步执行 - 考虑调整任务执行频率
- 优化任务代码性能
- 使用
-
集群环境下重复执行:
- 实现分布式锁
- 使用Quartz集群模式
- 或通过业务逻辑去重
【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱:
cloudbbs@huaweicloud.com
- 点赞
- 收藏
- 关注作者
评论(0)