2.1.12 Timing Tasks
The Spring framework comes with task scheduling capabilities that are like a lightweight Quartz and are easy to use without relying on other JAR packages.
Simply add @EnableScheduling to the project master startup class to turn on task scheduling
@SpringBootApplication @EnableScheduling public class LearnApplication { public static void main(String[] args) { SpringApplication.run(LearnApplication.class, args); } }
2.1.12.1 Simple Timing Tasks
@Component public class TestTask { @Scheduled(cron = "0/10 * * * * *") public void testTask1() { System.out.println("[Task 1) Test Timing Task" + LocalDateTime.now()); } }
As mentioned above, configuring a simple timed task can use it simply by adding the @Shceduled annotation to the scheduling method.
2.1.12.2 Asynchronous Timed Tasks
@Component // Turn on Asynchronous Support @EnableAsync public class TestTask { @Scheduled(cron = "0/10 * * * * *") // Method uses asynchronous execution, creating one thread per task to execute the task @Async public void testTask1() { System.out.println("[Task 1) Test Timing Task" + LocalDateTime.now() + " " + Thread.currentThread().getName()); for (int i = 0; i < 20; i++) { try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("[Task 1) Hibernate" + (i + 1) + "Seconds test timer task" + LocalDateTime.now() + " " + Thread.currentThread().getName()); } } }
Often in our project scheduling tasks, there are scenarios where the next scheduled task needs to be executed before the current task has been completed, in which case the scheduled task needs to be executed asynchronously.
@EnableAsync turns on Asynchronous Support
@Async tag task executes asynchronously (next task will start at the next configuration time, without waiting for the current task to finish executing)
2.1.12.3 Dynamic Timing Tasks
When we write a timed task, the process is roughly coding - > configuring the execution cycle - > starting the service.
The current execution cycle we configure is 8 a.m. every day, when we have a day and need to change at 8 p.m. every day, our operation flow is: modify the execution cycle - > new version packaging - > stop - > start the new version of the service.The whole process line has many steps and uncontrollable factors.
So how do we not stop updating our execution cycle?
So let's simulate storing the cron expression in MySQL.
1) Define cron-related service s
// Expression-related interfaces public interface SwitchService { /** * Get the latest cron expression * * @param taskId Task ID * @return Latest cron expression */ String getCron(String taskId); /** * Modify cron expression */ void modify(); }
// Expression-related interface implementation @Service public class SwitchServiceImpl implements SwitchService { private static String DB_CRON = ""; @Override public String getCron(String taskId) { System.out.println("Execute database queries DB_CRON " + LocalDateTime.now()); return DB_CRON; } @Override public void modify() { DB_CRON = "0/20 * * * * *"; System.out.println("Modify the database DB_CRON " + LocalDateTime.now()); } }
Simulate modifications and queries here
2) Create specific task execution
@Component public class DynamicCronTask implements SchedulingConfigurer { // Simulate current task ID private String TASK_ID = "5001"; @Autowired private SwitchService switchService; private String SpringDynamicCronTask() { // Default execution every 5 seconds String cron = "0/5 * * * * ?"; //Get the configuration corn s expression from the database String dbCron = switchService.getCron(TASK_ID); // Use the default expression when the query is empty if (StringUtils.isNotBlank(dbCron)) { return dbCron; } return cron; } @Override public void configureTasks(ScheduledTaskRegistrar scheduledTaskRegistrar) { scheduledTaskRegistrar.addTriggerTask(new Runnable() { @Override public void run() { // Task logic System.out.println("Execute Task Logic...." + LocalDateTime.now()); } }, new Trigger() { @Override public Date nextExecutionTime(TriggerContext triggerContext) { String s = SpringDynamicCronTask(); // Task triggers that modify the execution cycle of a task CronTrigger trigger = new CronTrigger(s); Date nextExec = trigger.nextExecutionTime(triggerContext); return nextExec; } }); } }
3) Start Services
View Execution Log
Execute database query DB_CRON 2020-06-09T10:33:30.001 Execute Task Logic....2020-06-09T10:33:35.002 Execute database query DB_CRON 2020-06-09T10:33:35.002 Execute Task Logic....2020-06-09T10:33:40.001 Execute database query DB_CRON 2020-06-09T10:33:40.001 Modify DB_in the databaseCRON 2020-06-09T10:33:42.085 Execute Task Logic....2020-06-09T10:33:45 Execute database query DB_CRON 2020-06-09T10:33:45 Execute Task Logic....2020-06-09T10:34:00.001 Execute database query DB_CRON 2020-06-09T10:34:00.001 Execute Task Logic....2020-06-09T10:34:20.002 Execute database query DB_CRON 2020-06-09T10:34:20.002
From the log, you can see that when the application starts, the execution cycle of the configuration is queried from the database first, then the timed task is executed, then the execution cycle is queried again after execution, and the next execution time is executed according to the modified execution time.
Effective time will not take effect immediately after the next execution time is over!!!