The background,
At work, sometimes the execution of some scheduled tasks may need to be dynamically modified, such as: To generate reports, some projects are configured to generate reports at 8 o ‘clock every day, and some projects are configured to generate reports at 10 o ‘clock every day. Such dynamic Task execution time can be easily realized by using Spring Task without considering distributed execution.
Second, requirements and implementation ideas
1. Can dynamically add a timed task.
inSpring
There is a class inThreadPoolTaskScheduler
, it can be achieved according to aCron expression
To schedule a task and return oneScheduledFuture
Object.
2. Can cancel the execution of timed tasks.
You can cancel this task by calling the cancel method on the scheduledFuture from the previous step.
3. Modify the execution time of the task dynamically.
- First cancel the mission.
- Then re-register a task.
4. Get an exception for the execution of a timed task
There is a setting in the ThreadPoolTaskScheduler classErrorHandler
Method, to their own implementation of the ErrorHandler can be.
Tip:
- in
Spring
In which we passed the@Scheduled
Annotations to achieve the timing task, the underlying also throughThreadPoolTaskScheduler
To do that. Can be achieved byScheduledAnnotationBeanPostProcessor
Class to view. ThreadPoolTaskScheduler
The default number of threads is 1, which needs to be changed according to the actual situation.
Three, code implementation
Only the code for dynamically registering and canceling timed tasks is given here.
package com.huan.study.task.jobs.tasks; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler; import org.springframework.scheduling.support.CronExpression; import org.springframework.scheduling.support.CronTrigger; import org.springframework.stereotype.Component; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.util.concurrent.ScheduledFuture; import java.util.concurrent.TimeUnit; /** * @Author Huan.fu 2021/7/8-2:46 PM */ @Component @SLF4J public class DynamicCronTask implements InitializingBean {/** * @Author Huan.fu 2021/7/8-2:46 PM */ @Component @SLF4J public class DynamicCronTask implements InitializingBean { @Autowired private ThreadPoolTaskScheduler taskScheduler; private ScheduledFuture<? > scheduledFuture; Override public void afterPropertiesSet() throws Exception {// Enable a task to log.info; scheduledFuture = register("* * * * * ?" ); New Thread(() -> {try {timeUnit.Seconds. Sleep (5); Log.info (" Undispatch "); scheduledFuture.cancel(false); The log. The info (" cancel result: "+ scheduledFuture. IsCancelled ()); Log.info (" Re-register a timed task: every 2 seconds "); register("*/2 * * * * ?" ); } catch (InterruptedException e) { e.printStackTrace(); } }).start(); } private ScheduledFuture<? > register(String cron) {// Higher versions use cronExpression, Low version USES CronSequenceGenerator Boolean validExpression = CronExpression. IsValidExpression (cron); The info (" cron: [{}] is legal: [{}] ", cron, validExpression); CronExpression expression = CronExpression.parse(cron); LocalDateTime nextExecTime = expression.next(LocalDateTime.now()); if (null ! = nextExecTime) {log.info(" The next execution time of the scheduled task is :[{}]", nextExecTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))); } return taskScheduler.schedule(new Runnable() {@Override public void run() {log.info(" I did this ");} return taskScheduler.schedule(new Runnable() {@Override public void run() {log.info()); } }, new CronTrigger(cron)); }}
IV. Results of execution
Five, complete code
https://gitee.com/huan1993/spring-cloud-parent/tree/master/springboot/springboot-task