Spring Boot Task Scheduling

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!!!

Keywords: Web Development Database Spring Hibernate MySQL

Added by Desbrina on Mon, 15 Jun 2020 21:10:56 +0300