Regular task scheduling function is very common in our development, to name a few examples: timing data that are out of date, time send E-mail and so on, to achieve timing task scheduling approach is also very diverse, this article mainly study the advantages and disadvantages of various implementation timing task scheduling, in order to provide some reference for future choices.

In this point

  • This section describes how to implement the Timer task.
  • This section describes how ScheduledExecutorService implements scheduled tasks.
  • This section describes how to use SpringBoot to implement scheduled tasks.
  • This section describes how to use SpringBoot to implement asynchronous tasks.

Timer Indicates the Timer task

Based on java.util.Timer of JDK, a program is scheduled to execute at a fixed interval after a certain delay by scheduling java.util.TimeTask.

Disadvantages:

  1. Cannot specify a time for execution.

  2. There is a potential bug that when a Timer runs multiple TimeTasks, if one of them does not catch an exception thrown, the other tasks will terminate automatically.

    public class DemoTimer {

    Private static final Long DELAY = 3000; Private static final Long PERIOD = 5000; Public static void main(String[] args) {TimerTask task = new TimerTask() {@override public void run() { System.out.println(" localDatetime.now () "); }}; Timer timer = new Timer(); timer.schedule(task, DELAY, PERIOD); }Copy the code

    }

ScheduledExecutorService Implements scheduled tasks

Alibaba’s development specification clearly states that ScheduledExecutorService is expected to be used instead of Timer.

When multiple threads process timed tasks in parallel, when a Timer runs multiple timeTasks, other tasks are automatically terminated as long as one of them does not catch an exception. ScheduledExecutorService does not have this problem.

Public class DemoScheduledExecutorService {/ / DELAY time private static final long DELAY = 3000; Private static final Long PERIOD = 5000; public static void main(String[] args) { Runnable task = new Runnable() { @Override public void run() { System.out.println(" localDatetime.now () "); }}; ScheduledExecutorService service = Executors.newSingleThreadScheduledExecutor(); service.scheduleAtFixedRate(task, DELAY, PERIOD, TimeUnit.MILLISECONDS); }}Copy the code

SpringBoot uses Spring Task to implement scheduled tasks

Implementation principles of automatic configuration

Spring provides us with a way to perform task scheduling asynchronously, providing TaskExecutor, TaskScheduler interfaces, Automatic configuration class and SpringBoot org. Springframework. Boot. Autoconfigure. Task. TaskSchedulingAutoConfiguration we injected they default to the realization of the: ThreadPoolTaskScheduler, essentially a wrapper around ScheduledExecutorService, enhances scheduling.

@ConditionalOnClass(ThreadPoolTaskScheduler.class)
@Configuration(proxyBeanMethods = false)
@EnableConfigurationProperties(TaskSchedulingProperties.class)
@AutoConfigureAfter(TaskExecutionAutoConfiguration.class)
public class TaskSchedulingAutoConfiguration {

	@Bean
	@ConditionalOnBean(name = TaskManagementConfigUtils.SCHEDULED_ANNOTATION_PROCESSOR_BEAN_NAME)
	@ConditionalOnMissingBean({ SchedulingConfigurer.class, TaskScheduler.class, ScheduledExecutorService.class })
	public ThreadPoolTaskScheduler taskScheduler(TaskSchedulerBuilder builder) {
		return builder.build();
	}

	@Bean
	@ConditionalOnMissingBean
	public TaskSchedulerBuilder taskSchedulerBuilder(TaskSchedulingProperties properties,
			ObjectProvider<TaskSchedulerCustomizer> taskSchedulerCustomizers) {
		TaskSchedulerBuilder builder = new TaskSchedulerBuilder();
		builder = builder.poolSize(properties.getPool().getSize());
		Shutdown shutdown = properties.getShutdown();
		builder = builder.awaitTermination(shutdown.isAwaitTermination());
		builder = builder.awaitTerminationPeriod(shutdown.getAwaitTerminationPeriod());
		builder = builder.threadNamePrefix(properties.getThreadNamePrefix());
		builder = builder.customizers(taskSchedulerCustomizers);
		return builder;
	}

}
Copy the code

New project, introduce dependencies

Spring Task is a module in the Spring Framework, and we just need to introduce the Spring-boot-starter dependency.

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
Copy the code

Write the configuration class @enablesCheduling

@Configuration
@EnableScheduling
public class ScheduleConfig {

}
Copy the code
  • @Configuration indicates that this is a Configuration class.
  • @enablescheduling Indicates that the Spring scheduled task scheduling function is enabled.

Define Scheduled tasks @Scheduled

@Component @Slf4j public class DemoTask { private final AtomicInteger counts = new AtomicInteger(); @scheduled (cron = "0/5 * * * * *") public void execute() {log.info("[Scheduled task executed for the first time]", counts. IncrementAndGet ()); }}Copy the code
  • @Component indicates that the class needs to be scanned for Spring container management.
  • Scheduled annotates methods that need to be Scheduled for execution and defines execution rules that must specify one of the cron, fixedDelay, or fixedRate attributes. Cron: Defines Spring Cron expressions. There are online Cron generators that you can use to write timed tasks that meet your requirements. FixedDelay: indicates the fixed execution interval, in milliseconds. Notice that the start time is the call completion time. FixedRate: fixed execution interval, in milliseconds. Notice that the start time is the time when the call starts.

The main start class

@SpringBootApplication public class SpringBootTaskApplication { public static void main(String[] args) { SpringApplication.run(SpringBootTaskApplication.class, args); }}Copy the code

Defining a configuration file

Spring Task schedules the configuration of tasks, corresponding to the TaskSchedulingProperties configuration class. SpringBoot allows you to customize these external configurations in YML or Properties, and it doesn’t matter if you don’t, auto configuration already gives you a set of default values.

Spring: Task: scheduling: thread-name-prefix: summerday- # The prefix of the thread name in the thread pool. Scheduling - is the default value, and pool: size: 10 # thread pool size is recommended based on your application. The default value is 1. Set shutdown: await-termination: true # When the application is closed, wait for the scheduled task to complete. The default value is false. You are advised to set it to true await-termination-period: 60 # The maximum waiting time for the task to complete, in seconds. The default value is 0, depending on your applicationCopy the code

Start project testing

2020-11-30 23:04:51.886 INFO 10936 -- [restartedMain] o.s.s.c.ThreadPoolTaskScheduler : TaskScheduler # perform scheduled tasks every 5s - [summerday-1] Com.hyh.task.DemoTask: [Timed task first run] 2020-11-30 23:05:00.002 INFO 10936 -- [summerday-1] com.hyh.task.DemoTask: [timed task first run] 2020-11-30 23:05:00.002 INFO 10936 -- [summerday-1] com.hyh.task.DemoTask: [timed task first run] 2020-11-30 23:05:00.002 INFO 10936 -- [summerday-1] com.hyh.task. 2020-11-30 23:05:05.002 INFO 10936 -- [summerday-2] com.hyh.task.DemoTask: 2020-11-30 23:05:10.001 INFO 10936 -- [summerday-1] com.hyh.task.DemoTask: [2020-11-30 23:05:15.002 INFO 10936 -- [summerday-3] com.hyh.task.DemoTask: [Fifth execution of scheduled task]Copy the code

SpringTask Asynchronous task

SpringTask Synchronize Scheduled tasks with @scheduled and @enablesCheduling. SpringTask also enables asynchronous Scheduled tasks with @async and @enableAsync.

SpringBoot automatic configuration class support for asynchronous: org. Springframework. Boot. The autoconfigure. Task. TaskExecutionAutoConfiguration

@async annotation added

@Async @Scheduled(cron = "0/1 * * * * *") public void asyncTask() { sleep(); System.out.println(thread.currentThread ().getName() + "async-task" + "localDateTime.now ()"); }Copy the code

@enableAsync annotation added

Public class schedulecfig {}Copy the code

The configuration file

Spring: Task: # Spring executionProperties This executor is used for Spring asynchronous tasks. Execution: thread-name-prefix: async- # thread pool thread name prefix. The default value is task-, and you are advised to set the pool based on your application. Core-size: 8 # Number of core threads. The default value is 8. Max-size: 20 # Maximum number of threads, the maximum number of threads in the thread pool, only after the buffer queue is full, the number of threads exceeding the core. Default: integer. MAX_VALUE keep-alive: 60s # Specifies the idle time allowed for a thread. Threads other than the core thread will be destroyed when the idle time expires. Default: 60 seconds queue-capacity: 200 # Buffer queue size, used to buffer the size of the queue to execute tasks. The default value is integer.max_value. Allow-core-thread-timeout: true # Specifies whether to allow the core thread to timeout, i.e. enable the thread pool to grow and shrink dynamically. The default is true. Shutdown: await-termination: true # Whether to wait for scheduled tasks to complete when the application is closed. The default value is false. You are advised to set it to true await-termination-period: 60 # The maximum waiting time for the task to complete, in seconds. The default value is 0, depending on your applicationCopy the code

Compare synchronous and asynchronous

@Component public class DemoAsyncTask { @Scheduled(cron = "0/1 * * * * *") public void synTask() { sleep(); System.out.println(thread.currentThread ().getName() + "syn-task execution, current time:" + localDateTime.now ()); } @Async @Scheduled(cron = "0/1 * * * * *") public void asyncTask() { sleep(); System.out.println(thread.currentThread ().getName() + "async-task" + "localDateTime.now ()"); } private void sleep() { try { Thread.sleep(10 * 1000); } catch (InterruptedException e) { e.printStackTrace(); }}}Copy the code

Enable synchronous and asynchronous tasks at the same time. Assume that the task takes a long time and the interval is short. The interval is 1s and the execution interval is 10s.

As you can see, the synchronization tasks are not executed at intervals of 1s, but are executed sequentially until the previous task completes. Asynchronous tasks, on the other hand, successfully parallelize serialized tasks.

Three things to watch ❤️

If you find this article helpful, I’d like to invite you to do three small favors for me:

  1. Like, forward, have your “like and comment”, is the motivation of my creation.

  2. Follow the public account “Java rotten pigskin” and share original knowledge from time to time.

  3. Also look forward to the follow-up article ing🚀

  4. [666] Scan the code to obtain the learning materials package