This is the 22nd day of my participation in the August More Text Challenge
Asynchronous tasks
concept
In SpringBoot, methods are annotated as asynchronous tasks using the @async annotation, and asynchronous tasks are submitted to run in a separate thread pool
use
-
Using the @ Async
@Slf4j @Component public class TestTaskFactory { /** * simulates a 5-second asynchronous task */ @Async public Future<Boolean> asyncTask1(a) throws InterruptedException { doTask("asyncTask1".5); return new AsyncResult<>(Boolean.TRUE); } /** * simulates a 2-second asynchronous task */ @Async public Future<Boolean> asyncTask2(a) throws InterruptedException { doTask("asyncTask2".2); return new AsyncResult<>(Boolean.TRUE); } /** * simulates a 3-second asynchronous task */ @Async public Future<Boolean> asyncTask3(a) throws InterruptedException { doTask("asyncTask3".3); return new AsyncResult<>(Boolean.TRUE); } /** * simulates a 5-second synchronization task */ public void task1(a) throws InterruptedException { doTask("task1".5); } /** * simulates a 2-second synchronization task */ public void task2(a) throws InterruptedException { doTask("task2".2); } /** * simulates a 3-second synchronization task */ public void task3(a) throws InterruptedException { doTask("task3".3); } private void doTask(String taskName, Integer time) throws InterruptedException { log.info("{} start execution, current thread name [{}]", taskName, Thread.currentThread().getName()); TimeUnit.SECONDS.sleep(time); log.info("{} execute successfully, current thread name [{}]", taskName, Thread.currentThread().getName()); }}Copy the code
-
The test class
@Slf4j @SpringBootTest @EnableAsync public class TestTaskFactoryTest{ @Autowired private TestTaskFactory taskFactory; /** * Test asynchronous task */ @Test public void asyncTaskTest(a) throws InterruptedException, ExecutionException { long start = System.currentTimeMillis(); Future<Boolean> asyncTask1 = taskFactory.asyncTask1(); Future<Boolean> asyncTask2 = taskFactory.asyncTask2(); Future<Boolean> asyncTask3 = taskFactory.asyncTask3(); Call get() to block the main thread asyncTask1.get(); asyncTask2.get(); asyncTask3.get(); long end = System.currentTimeMillis(); log.info("All asynchronous tasks are completed, total time: {} ms", (end - start)); } /** * Test synchronization task */ @Test public void taskTest(a) throws InterruptedException { long start = System.currentTimeMillis(); taskFactory.task1(); taskFactory.task2(); taskFactory.task3(); long end = System.currentTimeMillis(); log.info("All synchronization tasks are completed, total time: {} ms", (end - start)); }}Copy the code
The thread pool
-
The thread pool interface for asynchronous tasks, TaskExecutor, inherits from JUC package executors
-
TaskExecutor has many implementations in SpringBoot
SimpleAsyncTaskExecutor
: No thread is reused, and a new thread is created for each callSyncTaskExecutor
: Executes tasks synchronously on the caller’s current thread, suitable for scenarios where multithreading is not requiredConcurrentTaskExecutor
:Executor
The adaptation class is used to convert Java’sExecutor
Objects are incorporated into Spring managementThreadPoolTaskExecutor
: common thread pool implementation, its essence is rightThreadPoolExecutor
The packaging, throughTaskExecutionAutoConfiguration
Perform automatic configuration
-
Configure an asynchronous task thread pool
Through the application.yaml file
You need to enable asynchronous tasks using the @EnableAsync annotation on the startup class or configuration class and configure the thread pool through the configuration file
spring:
task:
execution:
pool:
# Maximum number of threads
max-size: 16
Number of core threads
core-size: 16
# Survival time
keep-alive: 10s
# queue size
queue-capacity: 100
Whether to allow core threads to timeout
allow-core-thread-timeout: true
# thread name prefix
thread-name-prefix: async-task-
Copy the code
Using the JavaConfig class
@Configuration
@EnableAsync
@Slf4j
public class ExecutorConfig implements AsyncConfigurer {
/** * asynchronous task execution thread pool **@return* /
@Bean(name = "asyncExecutor")
public ThreadPoolTaskExecutor asyncExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(10);
executor.setQueueCapacity(1000);
executor.setKeepAliveSeconds(600);
executor.setMaxPoolSize(20);
executor.setThreadNamePrefix("async-task-");
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
executor.initialize();
return executor;
}
@Override
public Executor getAsyncExecutor() {
return asyncExecutor();
}
@Override
public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
return (throwable, method, objects) -> {
log.error("Asynchronous task execution exception, message {}, method {}, params {}", throwable, method, objects); }; }}Copy the code
Timing task
concept
Annotate methods as Scheduled tasks using @scheduled, and SpringBoot will place the methods into the thread pool for execution on a Scheduled basis according to the configuration items in the annotations
use
-
Using the @ Scheduled
@Component @Slf4j public class TestTaskJob { /** * Execute */ every 10s @Scheduled(cron = "0/10 * * * * ?" ) public void job1(a) { log.info([job1] start execution: {}, DateUtil.formatDateTime(new Date())); } /** * fixed interval */ is executed in 2s intervals starting from the boot time @Scheduled(fixedRate = 2000) public void job2(a) { log.info("[job2] start: {}", DateUtil.formatDateTime(new Date())); } /** * From the start time, the delay is 5s, and the interval is 4s * fixed waiting time */ @Scheduled(fixedDelay = 4000, initialDelay = 5000) public void job3(a) { log.info("[job3] start execution: {}", DateUtil.formatDateTime(newDate())); }}Copy the code
-
@ Scheduled parameters
- Zone: the zone
- FixedDelay: the number of milliseconds after the last execution
- FixedRate: How many milliseconds have elapsed since the last execution started
- InitialDelay: the number of milliseconds to delay the first execution
- FixedDelayString, fixedRateString, initialDelayString: It is a string of characters. Placeholders can be used, for example
${job.fixedDelay}
- Corn: corn is an expression in the syntax
[second] [minute] [hour] [day] [month] [week] [year]
Years can be omitted
The thread pool
-
The implementation of the scheduled task thread pool is ThreadPoolTaskScheduler, which wraps the JDK ScheduledExecutorService
-
SchedulingConfiguration configuration class defines ScheduledAnnotationBeanPostProcessor the Bean, which scans the @ Scheduled annotations, and through the agent get method to create a thread to execute, submitted to the thread pool
-
Thread pool configuration
Through the application.yaml file
You need to enable asynchronous tasks with the @enablesCheduling annotation on the startup class or configuration class and configure thread pools through the configuration file
spring: task: scheduling: pool: size: 20 thread-name-prefix: schedule-job- Copy the code
Using the JavaConfig class
@Configuration @EnableScheduling public class ExecutorConfig implements SchedulingConfigurer { /** * Thread pool used by scheduled tasks **@return* / @Bean(destroyMethod = "shutdown", name = "taskScheduler") public ThreadPoolTaskScheduler taskScheduler(a) { ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler(); scheduler.setPoolSize(10); scheduler.setThreadNamePrefix("schedule-task-"); scheduler.setAwaitTerminationSeconds(600); scheduler.setWaitForTasksToCompleteOnShutdown(true); return scheduler; } @Override public void configureTasks(ScheduledTaskRegistrar scheduledTaskRegistrar) { ThreadPoolTaskScheduler taskScheduler = taskScheduler(); scheduledTaskRegistrar.setTaskScheduler(taskScheduler); }}Copy the code