On Spring timing task

Keywords: Spring Quartz


Three kinds of timed tasks are based on principle

Spring boot configuration timing tasks mainly include Spring Schedule, TimeTask provided by JDK and third-party quartz framework

  • SpringBoot starts a scheduled task, which is mainly divided into the following two steps:
  1. The Scheduled task method needs to be annotated with @ Scheduled
  2. Configure @ enablesscheduling to enable Scheduled tasks. The @ Scheduled annotation can configure fixedRate execution at a fixed frequency (if it times out, it will be executed immediately after the current method execution is completed), fixedDelay execution at a fixed interval (calculated from the end time of the last task) and user-defined cron expressions. By default, Spring Schedule will create a single thread pool to execute Scheduled tasks (Spring will search the relevant thread pool definitions, or search the unique TaskExecutor bean in the context, or search the Executor bean named "taskExecutor". If both cannot be resolved, SimpleAsyncTaskExecutor will be used to process asynchronous method calls). When multiple tasks need to be concurrent (or need to execute at the same time), the task scheduler will have time drift. Therefore, it is usually necessary to customize a thread pool ThreadPoolTaskScheduler for Scheduled tasks
  • TimeTask sorts the tasks in the heap according to the next execution time. Each time, the minimum time in the heap is compared with the current system time. If the current time is greater than the execution time of the next task, it will be executed and the task will be removed from the minimum heap. Therefore, Timer timed tasks are single thread + heap scheduling + polling, which is not suitable for multi task management
  • quartz can execute at a specific time through cron expression. Each time a task is executed, a new task class object will be created, and throwing an exception will not affect the next task execution, but the Timer throws an exception, and the whole Timer life cycle will end. quartz supports persistence, transaction management and cluster mode, which has certain advantages over multi scheduled task scheduling management


Concurrent configuration of multiple scheduled tasks

Spring Schedule configures multi timed task concurrency. Generally, you need to customize the thread pool. There are two main ways

  • The first method requires @ Async("specify thread pool") when using it
 @Configuration
 @EnableAsync
 public class ThreadPoolTaskConfig {

     	private static final int corePoolSize = 10;       		// Number of core threads (default threads)
     	private static final int maxPoolSize = 100;			    // Maximum number of threads
     	private static final int keepAliveTime = 10;			// Allowed thread idle time (unit: default is seconds)
     	private static final int queueCapacity = 200;			// Number of buffer queues
     	private static final String threadNamePrefix = "Async-Service-"; // Thread pool name prefix
     	
     	@Bean("taskExecutor") // The name of the bean. The default method name is lowercase
     	public ThreadPoolTaskExecutor getAsyncExecutor(){
     		ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
     		executor.setCorePoolSize(corePoolSize);   
     		executor.setMaxPoolSize(maxPoolSize);
     		executor.setQueueCapacity(queueCapacity);
     		executor.setKeepAliveSeconds(keepAliveTime);
     		executor.setThreadNamePrefix(threadNamePrefix);
     		
     		// Processing strategy of thread pool for rejecting tasks
     		executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
     		// initialization
     		executor.initialize();
     		return executor;
     	}
     }
  • The second way is to directly implement the AsyncConfigurer interface and rewrite the getAsyncExecutor method
@Configuration
@EnableAsync
public class AppConfig implements AsyncConfigurer {

     @Override
     public Executor getAsyncExecutor() {
         ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
         executor.setCorePoolSize(7);
         executor.setMaxPoolSize(42);
         executor.setQueueCapacity(11);
         executor.setThreadNamePrefix("MyExecutor-");
         executor.initialize();
         return executor;
     }

     @Override
     public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
         return new MyAsyncUncaughtExceptionHandler();
     }
}


Dynamic timed task


Timed task Demo

Posted by shaitand on Tue, 30 Nov 2021 12:01:57 -0800