TaskScheduler是Spring框架提供的任务调度接口,用于统一管理定时任务的触发与执行。它封装了不同的调度实现(如JDK的ScheduledThreadPoolExecutor、Quartz等),提供了丰富的调度方法,支持基于固定速率、固定延迟、Cron表达式等多种调度策略。
引言
在日常开发中,定时任务是常见的功能需求,例如数据同步、日志清理、报表生成等。传统的静态定时任务(如基于@Scheduled注解)虽然实现简单,但无法满足任务动态添加、修改、删除的场景。本文将详细介绍如何基于Spring Boot内置的TaskScheduler,实现一套灵活可扩展的动态定时任务系统,帮助开发者解决动态调度需求。
核心概念与原理
TaskScheduler 简介
TaskScheduler是Spring框架提供的任务调度接口,用于统一管理定时任务的触发与执行。它封装了不同的调度实现(如JDK的ScheduledThreadPoolExecutor、Quartz等),提供了丰富的调度方法,支持基于固定速率、固定延迟、Cron表达式等多种调度策略。
在Spring Boot中,当引入spring-context依赖(默认已包含在spring-boot-starter中)时,会自动配置ThreadPoolTaskScheduler(TaskScheduler的默认实现),无需额外引入第三方调度框架,降低了开发成本。
动态定时任务核心逻辑
动态定时任务的核心在于动态管理,即支持在应用运行过程中,对任务进行添加、更新、删除操作。其实现逻辑如下:
- 任务存储:使用线程安全的容器(如ConcurrentHashMap)存储任务信息,确保多线程环境下的操作安全性。
- 任务调度:通过TaskScheduler的schedule(Runnable task, Trigger trigger)方法,将任务与触发规则(如CronTrigger)绑定,返回ScheduledFuture对象用于后续任务控制。
- 任务更新/删除:更新任务时,先通过旧任务的ScheduledFuture对象取消任务,再重新创建新任务并调度;删除任务时,直接通过ScheduledFuture取消任务并从容器中移除。
完整实现
任务实体类(ScheduledTask)
定义任务实体,存储任务的核心信息(任务ID、Cron表达式、描述、执行逻辑、调度结果等):
/**
* 定时任务实体类
* 封装任务信息、调度规则及调度结果
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class ScheduledTask {
// 任务唯一标识(用于动态管理)
private String taskId;
// 任务Cron表达式(调度规则)
private String cronExpression;
// 任务描述(备注信息)
private String description;
// 任务执行逻辑(Runnable接口实现)
private Runnable task;
// 调度结果(用于取消任务)
private ScheduledFuture<?> scheduledFuture;
/**
* 构建任务执行逻辑
* 可根据实际需求自定义任务内容
*/
public void buildTask() {
this.task = () -> {
// 任务执行内容(示例:打印任务信息)
System.out.printf("[%s] 动态定时任务执行 - 任务ID:%s,描述:%s%n",
System.currentTimeMillis(), taskId, description);
// 实际业务逻辑可在此处扩展(如数据同步、文件处理等)
};
}
/**
* 基于Cron表达式创建触发规则
* @return Trigger 触发规则
*/
public Trigger buildTrigger() {
return new CronTrigger(cronExpression);
}
/**
* 调度任务(通过TaskScheduler执行)
* @param taskScheduler 任务调度器
*/
public void schedule(TaskScheduler taskScheduler) {
this.scheduledFuture = taskScheduler.schedule(task, buildTrigger());
}
/**
* 取消任务(停止调度)
* @param mayInterruptIfRunning 是否允许中断正在执行的任务
* @return boolean 取消结果(true:取消成功,false:取消失败)
*/
public boolean cancelTask(boolean mayInterruptIfRunning) {
if (scheduledFuture != null && !scheduledFuture.isCancelled()) {
return scheduledFuture.cancel(mayInterruptIfRunning);
}
returnfalse;
}
}
任务调度器配置(TaskSchedulerConfig)
配置ThreadPoolTaskScheduler,自定义线程池参数(如核心线程数、线程名称前缀等),确保任务调度的高效性和稳定性:
/**
* 任务调度器配置类
* 自定义ThreadPoolTaskScheduler参数,优化调度性能
*/
@Configuration
public class TaskSchedulerConfig {
/**
* 配置TaskScheduler实例
* @return TaskScheduler 任务调度器
*/
@Bean
public TaskScheduler taskScheduler() {
ThreadPoolTaskScheduler taskScheduler = new ThreadPoolTaskScheduler();
// 核心线程数(根据任务数量调整,避免线程过多导致资源浪费)
taskScheduler.setPoolSize(5);
// 线程名称前缀(便于日志排查)
taskScheduler.setThreadNamePrefix("dynamic-task-scheduler-");
// 任务拒绝策略(当线程池满时,直接抛出异常)
taskScheduler.setRejectedExecutionHandler((runnable, executor) -> {
throw new RuntimeException("任务调度线程池已满,无法执行新任务:" + runnable.getClass().getName());
});
// 初始化调度器(必须调用,否则无法生效)
taskScheduler.initialize();
return taskScheduler;
}
}
任务管理器(TaskManager)
核心服务类,负责任务的添加、更新、删除、查询等动态管理操作,使用ConcurrentHashMap存储任务,确保线程安全:
/**
* 定时任务管理器
* 提供任务的动态管理(添加、更新、删除、查询)
*/
@Service
public class TaskManager {
// 线程安全的任务容器(key:taskId,value:ScheduledTask)
private final Map<String, ScheduledTask> taskMap = new ConcurrentHashMap<>();
// 注入Spring配置的TaskScheduler
@Autowired
private TaskScheduler taskScheduler;
/**
* 添加定时任务
* @param taskId 任务ID(唯一)
* @param cronExpression Cron表达式
* @param description 任务描述
* @return boolean 添加结果(true:成功,false:任务已存在)
*/
public boolean addTask(String taskId, String cronExpression, String description) {
// 校验任务是否已存在
if (taskMap.containsKey(taskId)) {
System.out.printf("任务ID:%s 已存在,添加失败%n", taskId);
returnfalse;
}
// 构建任务实例
ScheduledTask task = new ScheduledTask();
task.setTaskId(taskId);
task.setCronExpression(cronExpression);
task.setDescription(description);
task.buildTask(); // 初始化任务执行逻辑
// 调度任务
task.schedule(taskScheduler);
// 存入任务容器
taskMap.put(taskId, task);
System.out.printf("任务添加成功 - 任务ID:%s,Cron表达式:%s%n", taskId, cronExpression);
returntrue;
}
/**
* 更新任务的Cron表达式(修改调度规则)
* @param taskId 任务ID
* @param newCronExpression 新的Cron表达式
* @return boolean 更新结果(true:成功,false:任务不存在)
*/
public boolean updateTaskCron(String taskId, String newCronExpression) {
// 校验任务是否存在
ScheduledTask oldTask = taskMap.get(taskId);
if (oldTask == null) {
System.out.printf("任务ID:%s 不存在,更新失败%n", taskId);
returnfalse;
}
// 1. 取消旧任务
boolean cancelResult = oldTask.cancelTask(false);
if (!cancelResult) {
System.out.printf("任务ID:%s 取消失败,更新中断%n", taskId);
returnfalse;
}
// 2. 创建新任务(复用旧任务的描述和执行逻辑,更新Cron表达式)
ScheduledTask newTask = new ScheduledTask();
newTask.setTaskId(taskId);
newTask.setCronExpression(newCronExpression);
newTask.setDescription(oldTask.getDescription());
newTask.buildTask();
// 3. 调度新任务
newTask.schedule(taskScheduler);
// 4. 替换任务容器中的旧任务
taskMap.put(taskId, newTask);
System.out.printf("任务更新成功 - 任务ID:%s,新Cron表达式:%s%n", taskId, newCronExpression);
returntrue;
}
/**
* 删除定时任务
* @param taskId 任务ID
* @return boolean 删除结果(true:成功,false:任务不存在)
*/
public boolean deleteTask(String taskId) {
// 校验任务是否存在
ScheduledTask task = taskMap.get(taskId);
if (task == null) {
System.out.printf("任务ID:%s 不存在,删除失败%n", taskId);
returnfalse;
}
// 1. 取消任务
boolean cancelResult = task.cancelTask(false);
if (!cancelResult) {
System.out.printf("任务ID:%s 取消失败,删除中断%n", taskId);
returnfalse;
}
// 2. 从容器中移除任务
taskMap.remove(taskId);
System.out.printf("任务删除成功 - 任务ID:%s%n", taskId);
returntrue;
}
/**
* 查询单个任务
* @param taskId 任务ID
* @return ScheduledTask 任务实例(null:任务不存在)
*/
public ScheduledTask getTask(String taskId) {
return taskMap.get(taskId);
}
/**
* 查询所有任务
* @return Collection<ScheduledTask> 所有任务列表
*/
public Collection<ScheduledTask> getAllTasks() {
return taskMap.values();
}
}
控制器(TaskController)
提供RESTful接口,方便前端或其他服务调用,实现任务的动态管理:
/**
* 定时任务API控制器
* 提供RESTful接口,实现任务的动态管理
*/
@RestController
@RequestMapping("/api/tasks")
public class TaskController {
@Autowired
private TaskManager taskManager;
/**
* 添加任务
* @param params 请求参数(taskId、cronExpression、description)
* @return ResponseEntity<Map<String, Object>> 响应结果
*/
@PostMapping
public ResponseEntity<Map<String, Object>> addTask(@RequestBody Map<String, String> params) {
Map<String, Object> result = new HashMap<>();
try {
// 校验参数
String taskId = params.get("taskId");
String cronExpression = params.get("cronExpression");
String description = params.getOrDefault("description", "默认任务");
if (taskId == null || cronExpression == null) {
result.put("success", false);
result.put("message", "任务ID和Cron表达式不能为空");
return ResponseEntity.badRequest().body(result);
}
// 调用任务管理器添加任务
boolean success = taskManager.addTask(taskId, cronExpression, description);
result.put("success", success);
result.put("message", success ? "任务添加成功" : "任务已存在");
return ResponseEntity.ok(result);
} catch (Exception e) {
result.put("success", false);
result.put("message", "任务添加失败:" + e.getMessage());
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(result);
}
}
/**
* 更新任务Cron表达式
* @param taskId 任务ID
* @param params 请求参数(newCronExpression)
* @return ResponseEntity<Map<String, Object>> 响应结果
*/
@PutMapping("/{taskId}/cron")
public ResponseEntity<Map<String, Object>> updateTaskCron(
@PathVariable String taskId,
@RequestBody Map<String, String> params) {
Map<String, Object> result = new HashMap<>();
try {
// 校验参数
String newCronExpression = params.get("newCronExpression");
if (newCronExpression == null) {
result.put("success", false);
result.put("message", "新的Cron表达式不能为空");
return ResponseEntity.badRequest().body(result);
}
// 调用任务管理器更新任务
boolean success = taskManager.updateTaskCron(taskId, newCronExpression);
result.put("success", success);
result.put("message", success ? "任务Cron更新成功" : "任务不存在");
return ResponseEntity.ok(result);
} catch (Exception e) {
result.put("success", false);
result.put("message", "任务更新失败:" + e.getMessage());
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(result);
}
}
/**
* 删除任务
* @param taskId 任务ID
* @return ResponseEntity<Map<String, Object>> 响应结果
*/
@DeleteMapping("/{taskId}")
public ResponseEntity<Map<String, Object>> deleteTask(@PathVariable String taskId) {
Map<String, Object> result = new HashMap<>();
try {
// 调用任务管理器删除任务
boolean success = taskManager.deleteTask(taskId);
result.put("success", success);
result.put("message", success ? "任务删除成功" : "任务不存在");
return ResponseEntity.ok(result);
} catch (Exception e) {
result.put("success", false);
result.put("message", "任务删除失败:" + e.getMessage());
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(result);
}
}
/**
* 查询单个任务
* @param taskId 任务ID
* @return ResponseEntity<Map<String, Object>> 响应结果
*/
@GetMapping("/{taskId}")
public ResponseEntity<Map<String, Object>> getTask(@PathVariable String taskId) {
Map<String, Object> result = new HashMap<>();
try {
ScheduledTask task = taskManager.getTask(taskId);
if (task != null) {
result.put("success", true);</doubaocanvas>
AI大模型学习福利
作为一名热心肠的互联网老兵,我决定把宝贵的AI知识分享给大家。 至于能学习到多少就看你的学习毅力和能力了 。我已将重要的AI大模型资料包括AI大模型入门学习思维导图、精品AI大模型学习书籍手册、视频教程、实战学习等录播视频免费分享出来。
一、全套AGI大模型学习路线
AI大模型时代的学习之旅:从基础到前沿,掌握人工智能的核心技能!

因篇幅有限,仅展示部分资料,需要点击文章最下方名片即可前往获取
二、640套AI大模型报告合集
这套包含640份报告的合集,涵盖了AI大模型的理论研究、技术实现、行业应用等多个方面。无论您是科研人员、工程师,还是对AI大模型感兴趣的爱好者,这套报告合集都将为您提供宝贵的信息和启示。

因篇幅有限,仅展示部分资料,需要点击文章最下方名片即可前往获
三、AI大模型经典PDF籍
随着人工智能技术的飞速发展,AI大模型已经成为了当今科技领域的一大热点。这些大型预训练模型,如GPT-3、BERT、XLNet等,以其强大的语言理解和生成能力,正在改变我们对人工智能的认识。 那以下这些PDF籍就是非常不错的学习资源。

因篇幅有限,仅展示部分资料,需要点击文章最下方名片即可前往获
四、AI大模型商业化落地方案

因篇幅有限,仅展示部分资料,需要点击文章最下方名片即可前往获
作为普通人,入局大模型时代需要持续学习和实践,不断提高自己的技能和认知水平,同时也需要有责任感和伦理意识,为人工智能的健康发展贡献力量
1562

被折叠的 条评论
为什么被折叠?



