Many of you have encountered some business logic that needs to be executed on a regular basis, and there are many solutions, such as MQ. Springboot provides a useful component called Schedule.

We all know that Spring creates a timed task, so esay, in three ways:

  • Based on annotations (@scheduled)
  • SchedulingConfigurer Based on interface
  • Set multithreaded timed tasks based on annotations

1. Based on Annotations (@scheduled)

Note that @Scheduled is serial, single-threaded by default, and when multiple tasks are started, the execution time of the task will be affected by the execution time of the previous task.

@Configuration
@EnableScheduling    // Enable a scheduled task
public class ScheduleTask {
    // This command is executed every 10 seconds
    @Scheduled(cron = "0/10 * * * *?")
    private void configureTasks(a) {
        System.out.println("I'm a timed task."); }}Copy the code

@Scheduled provides three additional ways to do this in addition to Cron: FixedRate, fixedDelay, initialDelay 1, cron expressions can be customized to execute tasks, but the execution is similar to fixedDelay, and is counted from the end time of the last method. 2. FixedDelay specifies the interval between the execution of a fixedDelay control method. If the last execution of a fixedDelay is blocked, the next execution of a fixedDelay control method will be executed after the last execution of a fixedDelay control method.

@Configuration
@EnableScheduling    // Enable a scheduled task
public class ScheduleTask {
    // This command is executed every 10 seconds
    @Scheduled(fixedDelay = 10000)
    private void configureTasks(a) {
        System.out.println("I'm a timed task."); }}Copy the code

3, fixedRate is according to the rate at which a certain implementation, from the starting time of the last method execution, if the last block up the method, the next is not executed, but in the blocked during this period the number of total should be performed, when no longer block, these all at once to perform, then according to the fixed rate to continue.

@Configuration
@EnableScheduling    // Enable a scheduled task
public class ScheduleTask {
    // This command is executed every 10 seconds
    @Scheduled(fixedRate = 10000)
    private void configureTasks(a) {
        System.out.println("I'm a timed task."); }}Copy the code

4. InitialDelay = 10000 indicates that the timer should be executed again after 10 seconds after the container is started.

@configuration@enablesCheduling // Enable scheduled task public class ScheduleTask {// After the container is started, the timer is executed 10 seconds later and every 10 seconds later. @Scheduled(initialDelay = 10000, fixedRate = 10000) private voidconfigureTasks() {
        System.out.println("I'm a timed task."); }}Copy the code

SchedulingConfigurer

Some of you might find it convenient to use the @scheduled annotation, but the downside is that when we change the execution cycle, we need to restart the application to take effect, which is somewhat inconvenient. To achieve real-time effectiveness, you can use interfaces to complete scheduled tasks.

  • The following example fetches the execution cycle time from the data and dynamically executes the scheduled task:
@Configuration      
@EnableScheduling   // Enable a scheduled task
public class DynamicScheduleTask implements SchedulingConfigurer {

    // Obtain the execution period of the task from data
    @Autowired
    private MyBatisMapper myBatisMapper;

    @Override
    public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
        taskRegistrar.addTriggerTask(
                //1. Add task content (Runnable)
                () -> System.out.println("Execute a dynamic scheduled task:" + LocalDateTime.now().toLocalTime()),
                //2. Set the execution cycle (Trigger)
                triggerContext -> {
                    //2.1 Obtain the execution period from the database
                    String cron = myBatisMapper.getCron();
                    //2.2 Return to Execution period (Date)
                    return newCronTrigger(cron).nextExecutionTime(triggerContext); }); }}Copy the code

The database table data is as follows:

All right, let’s run the test and see

Executing a dynamic scheduled task:17:17:00.008999Executing a dynamic scheduled task:17:17:20.002501Executing a dynamic scheduled task:17:17:30.001786Executing a dynamic scheduled task:17:17:40.005512Executing a dynamic scheduled task:17:17:50.005870Executing a dynamic scheduled task:17:18:00.002189Executing a dynamic scheduled task:17:18:10.001910
Copy the code

We can see that the mission is executed every 10 seconds. So now you want to do it every 5 seconds, what do you do? At this time, we only need to modify the database data, without restarting.

Executing a dynamic scheduled task:17:18:30.000902Executing a dynamic scheduled task:17:18:40.001392Executing a dynamic scheduled task:17:18:45.005027Executing a dynamic scheduled task:17:18:50.001367Executing a dynamic scheduled task:17:18:55.001356Executing a dynamic scheduled task:17:19:00.001582Executing a dynamic scheduled task:17:19:05.005676Executing a dynamic scheduled task:17:19:10.001258Executing a dynamic scheduled task:17:19:15.005272
Copy the code

Success is executed every 5 seconds. Isn’t it very hi

Set multithreaded timed tasks based on annotations

The @scheduled execution cycle tasks are influenced by the last time a task was executed. Then you can enable multi-threading to perform periodic tasks.

@EnableScheduling   // 1. Enable the scheduled task
@EnableAsync        // 2. Enable multithreading
@Component
public class MultiThreadScheduleTask {

    @Async
    @Scheduled(fixedDelay = 1000)  // The interval is 1 second
    public void first(a) throws InterruptedException {
        System.out.println("First scheduled task begins:" + LocalDateTime.now().toLocalTime() + "\r\n thread:" + Thread.currentThread().getName());
        Thread.sleep(1000 * 10);
    }

    @Async
    @Scheduled(fixedDelay = 2000)
    public void second(a) {
        System.out.println("Second scheduled task begins:" + LocalDateTime.now().toLocalTime() + "\r\n thread:"+ Thread.currentThread().getName()); }}Copy the code

Let’s restart the project and see what the console outputs:

Second scheduled task start: 17:27:01.024288 Thread: task-4 First scheduled task start: 17:27:01.024393 Thread: task-7 First scheduled task start: 17:27:02.027932 Thread: Task-4 The second scheduled task starts at 17:27:05.021294 Thread: task-1 The first scheduled task starts at 17:27:05.021533 Thread: task-1 The first scheduled task starts at 17:27:06.014213Copy the code

See, with multithreading enabled, the execution time of the first task is also not limited by its own execution time. The two missions are also mutually exclusive.