“This is the 16th day of my participation in the August More Text Challenge. For details, see: August More Text Challenge.”
Let’s take a look at Spring Boot 2.x to understand the schedule of scheduled tasks
Based on the above code changes
Source: github.com/langyastudi…
Spring-fram /spring-fram…
Work often involves asynchronous tasks, usually using multi-threaded techniques such as a thread pool ThreadPoolExecutor, which executes as follows (image from the network) :
When developing with Spring, in addition to the @enableAsync and @Async annotations, you need to define a Bean of type TaskExecutor. Fortunately the Spring Boot TaskExecutionAutoConfiguration provides automatic configuration, It automatically registers a ThreadPoolTaskExecutor (TaskExecutor implementation class) for a Bean named applicationTaskExecutor, So in Spring Boot, you only need to use @enableAsync and @async annotations to complete multi-threaded asynchronous operations.
Using the step
Spring Boot provides asynchronous multi-threaded task functionality by:
-
@EnableAsync
Enable support for asynchronous multithreaded tasks on the configuration class or Main class
-
@Async
Annotate the asynchronous multithreaded tasks that need to be performed. It can be applied to a class or a method. All methods applied to a class are asynchronous.
Enable support for asynchronous multithreaded tasks in the entry class:
@SpringBootApplication
@EnableAsync
public class Application
{
public static void main(String[] args)
{... }}Copy the code
Define a class that contains asynchronous multithreaded tasks:
@Component
@Log4j2
public class AsyncTask
{
@Async
public void loopPrint(Integer i)
{
log.info("async task:"+ i); }}Copy the code
This is tested with CommandLineRunner:
@Bean
CommandLineRunner asyncTaskClr(AsyncTask asyncTask)
{
return (args) -> {
for (int ix=0; ix<10; ix++) { asyncTask.loopPrint(ix); }}; }Copy the code
The execution results of the program are as follows:
[task-1] com.langyastudio.springboot.common.middleware.task.AsyncTask : async task:0
[task-1] com.langyastudio.springboot.common.middleware.task.AsyncTask : async task:8
[task-1] com.langyastudio.springboot.common.middleware.task.AsyncTask : async task:9
[task-2] com.langyastudio.springboot.common.middleware.task.AsyncTask : async task:1
[task-3] com.langyastudio.springboot.common.middleware.task.AsyncTask : async task:2
[task-7] com.langyastudio.springboot.common.middleware.task.AsyncTask : async task:6
[task-6] com.langyastudio.springboot.common.middleware.task.AsyncTask : async task:5
[task-8] com.langyastudio.springboot.common.middleware.task.AsyncTask : async task:7
[task-5] com.langyastudio.springboot.common.middleware.task.AsyncTask : async task:4
[task-4] com.langyastudio.springboot.common.middleware.task.AsyncTask : async task:3
Copy the code
As you can see, instead of using the main thread, restartedMain, asynchronous tasks use a pool of eight threads with names beginning with task-. The execution results are out of order, which means that tasks are executed concurrently.
TaskExecutor
How to customize the thread pool information such as the number of threads and thread name prefix? The answer is ThreadPoolTaskExecutor, which allows you to customize information such as the number of threads, thread name prefixes, and so on for a specific asynchronous multithreaded task.
This way you can specify a ThreadPoolTaskExecutor for a specific task when there are multiple different asynchronous multi-threaded tasks on the system. Spring Boot provides the TaskExecutorBuilder Bean, which you can use to create our custom ThreadPoolTaskExecutor.
Example:
@Bean
ThreadPoolTaskExecutor customTaskExecutor(TaskExecutorBuilder builder)
{
return builder.threadNamePrefix("langyatask")
.corePoolSize(5)
.build();
}
Copy the code
Specify a TaskExecutor in the comment for a multithreaded asynchronous task:
@Component
@Log4j2
public class AsyncTask
{
@Async("customTaskExecutor")
public void loopPrint(Integer i)
{
log.info("async task:"+ i); }}Copy the code
The number of threads, thread name prefix, and so on are executed according to the values defined by customTaskExecutor.
Future
Sometimes we want not only to execute tasks asynchronously, but also to have a return value when the task is completed. Java provides a generic Future interface to receive the result of the task execution. Spring Boot also provides support for this. Use classes such as AsyncResult that implement the ListenableFuture interface as vectors for the return value.
For example, if you want to return a value of type String, you can change the return value to:
@Async("customTaskExecutor")
public ListenableFuture<String> loopPrint(Integer i)
{
String res = "async task:" + i;
log.info(res);
return new AsyncResult<>(res);
}
Copy the code
Call return value:
@Autowired
private AsyncTask asyncTask;
// Block the call
asyncTask.loopPrint(1).get(a);// Call for a limited time
asyncTask.loopPrint(2).get(1, TimeUnit.SECONDS)
Copy the code
You can not use @Async
in conjunction with lifecycle callbacks such as @PostConstruct
. To asynchronously initialize Spring beans, you currently have to use a separate initializing Spring bean that then invokes the @Async
annotated method on the target, as the following example shows:
public class SampleBeanImpl implements SampleBean {
@Async
void doSomething(a) {
// ...}}public class SampleBeanInitializer {
private final SampleBean bean;
public SampleBeanInitializer(SampleBean bean) {
this.bean = bean;
}
@PostConstruct
public void initialize(a) { bean.doSomething(); }}Copy the code
Reference documents: Liao Xuefeng, “From enterprise development to Cloud Native Microservices: Spring Boot Combat”, etc