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.

inSpringThere is a class inThreadPoolTaskScheduler, it can be achieved according to aCron expressionTo schedule a task and return oneScheduledFutureObject.

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.

  1. First cancel the mission.
  2. Then re-register a task.

4. Get an exception for the execution of a timed task

There is a setting in the ThreadPoolTaskScheduler classErrorHandlerMethod, to their own implementation of the ErrorHandler can be.

Tip:

  1. inSpringIn which we passed the@ScheduledAnnotations to achieve the timing task, the underlying also throughThreadPoolTaskSchedulerTo do that. Can be achieved byScheduledAnnotationBeanPostProcessorClass to view.
  2. ThreadPoolTaskSchedulerThe 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