Troubleshoot problems with the @ Scheduled timer when using springboot

  • 2021-12-09 08:50:41
  • OfStack

Problems encountered by directory @ Scheduled timer: 1. Several parameters of @ Scheduled annotation 1. Can be configured by configuration file 2. What pits are used by timer tasks that cannot be configured by configuration file (with the same effect) @ Scheduled 1. What pits are used? 1. Single Threaded 2. @ Async and @ EnableAsync2. Use Multithreaded Summary 1

Problems encountered with @ Scheduled timer

This annotation @ Scheduled really brings us great convenience. We only need to add this annotation and set it up according to our needs to use timed tasks.

However, we should pay attention to the fact that @ Scheduled will not be executed on time.

Because the timing tasks using @ Scheduled are executed asynchronously, but different timing tasks are not parallel! ! ! ! ! ! ! !

Before one of the scheduled tasks is finished, the other scheduled tasks will not be executed even when it is time to execute, and they will be queued.

That is, if you want your different timed tasks to be executed at the right time without affecting each other, then you'd better make your timed task method itself asynchronous, so that,

In fact, a timed task is equivalent to calling a thread to execute the task, and it ends in an instant. Of course, it can be reluctantly regarded as a task that will be executed regularly.

Let's talk about several parameters of @ Scheduled annotation under 1

1. You can configure it through a configuration file

Use an expression that represents one execution every 1 second. If the last method exceeds the timing time and has not been executed, the next timing will not be executed.

The next timed task will be executed immediately after the last method execution

When the project starts, this method will not be executed immediately, but will be executed according to the law of timing expression. For example, here, it will not be executed until 1 second.


@Scheduled(cron="0/1 * * * * ?")   

Use a fixed rate. This expression means that it is executed once every 1 second. If the last method has not finished executing for more than 1 second, the next task will not be executed until

When the last method is finished, the next timing will be executed immediately.

This method will be implemented immediately when the project starts, and then it will be implemented according to the law.


@Scheduled(fixedRateString="1000")   //  Unit: milliseconds 

The difference between this method and the previous one is that one more parameter is added, which is an initialization parameter.

After adding initialDelayString, it will not be executed immediately at the beginning of startup, but will not be executed until 10 seconds later, even if fixedRateString

1 second. It will not be executed for the first time until 10 seconds later.

Note: initialDelayString cannot be used in combination with cron.


@Scheduled(fixedRateString="1000",initialDelayString="10000")

Use a fixed delay. This expression means to execute again 1 second after each execution. Every time you execute, no matter how long you execute, the next execution will be in the previous method

After execution, execute again after another 1 second.

This method will be implemented immediately when the project starts, and then it will be implemented according to the law.


@Scheduled(fixedDelayString="1000")

2. Not configurable through a configuration file (same effect)

   @Scheduled(fixedRate=1000)      //  They all accept 1 A long Parameters of type 
   @Scheduled(fixedDelay=1000)
   @Scheduled(fixedRate=1000,initialDelay=10000)

Paste the rules of cron expression under 1 here:

字段 允许值 允许的特殊字符
0-59 , - * /
小时 0-23 , - * /
日期 1-31 , - * ? / L W C
月份 1-12 或者 JAN-DEC , - * /
星期 1-7 或者 SUN-SAT , - * ? / L C #
年(可选) 留空, 1970-2099 , - * /

Those pits used by timed task @ Scheduled

@ Scheduled is a self-contained annotation of spring, which is single-threaded by default and is often used for timing tasks. However, if it is a cluster version of the machine, consider adding distributed locks or using distributed timing tasks instead.

1. What pits are used?

1. Single-threaded

Because @ Scheduled is single-threaded by default, if there are two tasks, A and B, task A will not execute if it is blocked.

2. @ Async and @ EnableAsync

In order to solve the thread blocking problem caused by single thread, we can use @ Async and @ EnableAsync annotations to deal with it asynchronously, so that different threads execute it, but this way also brings a new problem, that is, if the task execution time of A is > If the task schedules the cycle time, the logic that the last task is not completed and the next task starts to execute again will occur, which is also risky. Therefore, it is best to use multithreading, and control the number of thread pools and thread names by yourself.

2. Use multithreading

It is necessary to implement the SchedulingConfigurer interface, and then customize the thread pool, so that anyone who uses the @ Scheduled annotation can use this thread pool, which also solves the two problems of the above comparison pit.


@Configuration
@EnableScheduling
public class ScheduleConfig implements SchedulingConfigurer {
    @Override
    public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
        taskRegistrar.setScheduler(taskExecutor());
    }
    @Bean
    public Executor taskExecutor() {
        return Executors.newScheduledThreadPool(20, (Runnable r) -> {
            Thread thread = new Thread(r);
            thread.setName(" Custom thread name ");
            return thread;
        });
    }
}

The above line 1


thread.setName( "Custom Thread Name" );

Is to set the thread name, which can be obtained through Thread. currentThread (). getName () to facilitate troubleshooting in the log.

Summary 1

If you want to use @ Scheduled in the cluster version, you need to add distributed locks to control it, or directly use distributed timing tasks such as Elasticjob or xxl-job.


Related articles: