To avoid face slapping, first write the version: Spring Boot 2.2.2.RELEASE

one

Spring Boot comes with a lightweight task scheduling framework that is easy to use.

  1. Add annotations@EnableSchedulingOf course, it needs to be placed on a class that can be scanned, such as start class, use@ConfigurationConfiguration class. Of course you have to put one@ComponentI have nothing to say about it except that it is not very normative.
  2. Add to methods that require timed execution@ScheduledAnnotation, and set scheduling mode, supported
    • cron
    • fixedDelay
    • fixedRate

It’s that simple.

two

Now we have two tasks A and B

Task A is executed at 5am and takes 2 hours

@Scheduled(cron = "0 0 5 * * *")
public void taskA(a) throws InterruptedException {
    log.info("taskA running");
    Thread.sleep(2 * 60 * 60 * 1000);// The simulation task takes 2 hours
}
Copy the code

Task B is on at 6:00

@Scheduled(cron = "0 0 6 * * *")
public void taskB(a) {
    log.info("taskB running");
}
Copy the code

Soul question: will mission B be executed as expected at 6 o ‘clock?

If you think you can execute it properly, you may have forgotten the title.

three

Conclusion: Task B cannot be executed at 6:00 because the scheduler has a thread pool size of 1.

Spring Boot will automatically configure it.

So let’s look at the comment @enablesCheduling, it says in the comment

By default, will be searching for an associated scheduler definition: either a unique org.springframework.scheduling.TaskScheduler bean in the context, or a TaskScheduler bean named “taskScheduler” otherwise; the same lookup will also be performed for a java.util.concurrent.ScheduledExecutorService bean. If neither of the two is resolvable, a local single-threaded default scheduler will be created and used within the registrar. When more control is desired, a @Configuration class may implement SchedulingConfigurer. This allows access to the underlying ScheduledTaskRegistrar instance.

By default, a scheduler is found, in the following order

  1. The only org. Springframework. Scheduling. TaskScheduler types of beans

  2. A name for taskScheduler org. Springframework. Scheduling. TaskScheduler types of beans

  3. The only Java. Util. Concurrent. ScheduledExecutorService types of beans

  4. A name for taskScheduler Java. Util. Concurrent. ScheduledExecutorService types of beans

  5. Create a single-threaded scheduler

If you want more control, you can write a configuration class that implements the SchedulingConfigurer interface. If you set a scheduler in this configuration class, you won’t look any further

It looks like we’re in case five.

four

@ EnableScheduling introduced SchedulingConfiguration, SchedulingConfiguration defines a ScheduledAnnotationBeanPostProcessor types of beans.

@Configuration
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public class SchedulingConfiguration {

	@Bean(name = TaskManagementConfigUtils.SCHEDULED_ANNOTATION_PROCESSOR_BEAN_NAME)
	@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
	public ScheduledAnnotationBeanPostProcessor scheduledAnnotationProcessor(a) {
		return newScheduledAnnotationBeanPostProcessor(); }}Copy the code

The code to set up the scheduler is in the finishRegistration method.

Discovery with code is actually done in the first case.

Where is the bean defined?

five

A (full) was (with) touch (luck) cable (gas), found a TaskSchedulingAutoConfiguration automatic configuration class, which defines the ThreadPoolTaskScheduler types of beans.

Let’s look at the conditions up here

  1. Famous called org. Springframework. Context. The annotation. InternalScheduledAnnotationProcessor bean is loaded, And the name is defined SchedulingConfiguration ScheduledAnnotationBeanPostProcessor name.

  2. The SchedulingConfigurer, TaskScheduler, and ScheduledExecutorService types are not loaded. This is also about scalability. The developer defines the associated beans and the framework does not configure them automatically.

@Bean
@ConditionalOnBean(
    name = {"org.springframework.context.annotation.internalScheduledAnnotationProcessor"})@ConditionalOnMissingBean({SchedulingConfigurer.class, TaskScheduler.class, ScheduledExecutorService.class})
public ThreadPoolTaskScheduler taskScheduler(TaskSchedulerBuilder builder) {
    return builder.build();
}
Copy the code

six

So how do you change the scheduler thread pool size

TaskSchedulingAutoConfiguration class defines the above methods need TaskSchedulerBuilder

@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

Can see the thread pool size is by reading the configuration Settings, which is set up spring.. Task scheduling. The pool. The size.

Of course, the above method is automatically configured by Spring Boot, you can also define your own, as long as you know which priority to look for.

See here must be true love, follow the wechat public number [Simple and Simple Spring] the first time to get updates