preface
when learning thread pool, we all know that the core parameters such as the number of core threads, the maximum number of threads and the thread factory of the thread pool are very important, so we should remember them by heart. However, some siege lions who have worked for five or six years may not be able to say how to initialize a global thread pool for use in different scenarios; Therefore, this article customizes the global thread pool based on the asynchronous annotation @ Async of Spring Boot. If it's old fellow, please bypass. Here are insignificant skill.
maven coordinates
<dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-lang3</artifactId> <version>3.7</version> </dependency> <dependency> <groupId>com.google.guava</groupId> <artifactId>guava</artifactId> <version>31.0.1-jre</version> </dependency>
Custom thread pool
parameters such as the number of core threads and the maximum number of threads can be defined in the configuration file. Here, for simplicity, they are directly assigned.
import com.google.common.util.concurrent.ThreadFactoryBuilder; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import java.util.concurrent.*; /** * @Author: Wiener * @Date: 2022/1/8 19:57 */ @Configuration public class AsyncTaskConfig { // Including the corePoolSize thread, redundant threads will wait for keepAliveTime for a long time. If there is no request to process, they will be destroyed by themselves @Bean("first-executor") public Executor firstExecutor() { ThreadFactory guavaFactory = new ThreadFactoryBuilder().setNameFormat("first-executor").build(); int curSystemThreads = Runtime.getRuntime().availableProcessors() * 2; ThreadPoolExecutor threadPool = new ThreadPoolExecutor(curSystemThreads, 32, 30L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>(), guavaFactory); threadPool.allowsCoreThreadTimeOut(); return threadPool; } //My task is used to specify the thread pool name @Bean("my-executor") public Executor myExecutor() { ThreadFactory guavaFactory = new ThreadFactoryBuilder().setNameFormat("my-executor").build(); int curSystemThreads = Runtime.getRuntime().availableProcessors() * 2; ThreadPoolExecutor threadPool = new ThreadPoolExecutor(curSystemThreads, 32, 30L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>(), guavaFactory); threadPool.allowsCoreThreadTimeOut(); return threadPool; } }
Create a threaded task using the @ Async annotation
Spring provides annotation @ Async support for task scheduling and asynchronous method execution. By marking @ Async annotation on the method, the method can be called asynchronously. Add @ Async annotation to the method that needs asynchronous execution, and specify the thread pool to use. Of course, you can write @ Async directly without specifying it.
service is defined as follows:
/** * Specify pool * @Author: Wiener * @Date: 2022/1/8 19:59 */ public interface AsyncTaskService { void executeAsyncTask(Integer i); void executeMyTask(Integer i); }
The implementation classes are as follows:
import lombok.extern.slf4j.Slf4j; import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Service; /** * @Author: Wiener * @Date: 2022/1/9 12:33 */ @Slf4j @Service public class AsyncTaskServiceImpl implements AsyncTaskService { @Async("first-executor") @Override public void executeAsyncTask(Integer i) { System.out.println("thread " + Thread.currentThread().getName() + " Perform asynchronous tasks:" + i); try { Thread.sleep(100); } catch (Exception e) { e.printStackTrace(); } System.out.println("end executeAsync"); } @Async("my-executor") @Override public void executeMyTask(Integer i) { System.out.println("---thread " + Thread.currentThread().getName() + " Perform asynchronous tasks:" + i); try { Thread.sleep(100); } catch (Exception e) { e.printStackTrace(); } System.out.println("---end executeAsync"); } }
Modify startup class and create test class
add the annotation @ EnableAsync in the startup class to support asynchronous operations. Then, create a controller:
import com.swagger.demo.service.AsyncTaskService; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; /** * @author Test thread pool */ @Slf4j @RestController @RequestMapping("/pool") public class GuavaController { @Autowired private AsyncTaskService asyncTaskService; @PostMapping("asyncTaskTest") public void asyncTaskTest() { // The request parameter is written as a fixed value asyncTaskService.executeAsyncTask(1); asyncTaskService.executeMyTask(200); System.out.println("All tasks finished."); } }
after starting the Spring Boot service, request the above API, and you can see the following log on the console:
thread first-executor Executing asynchronous tasks: 1 All tasks finished. ---thread my-executor Executing asynchronous tasks: 200 end executeAsync ---end executeAsync
From the execution results, the two actuators we configured were successful.
Summary | @ Async usage
when using @ Async annotation, there are the following points to pay attention to,
- Return value: if no return value is required, set the method return value to void directly; If necessary, the return value is carried by AsyncResult or completable future.
- Custom executors, such as @ async ("the given executor").
- How to start asynchrony: @ async annotation must be called between different classes, such as class A - > class B Methodc() (@ async added to methodc of class B). If a method is nested in the same class, it will be executed synchronously, such as class A methodB() - > class A@ Async methodC().
- @Async is added to the class, which means that all methods of the class are executed asynchronously, and the annotation on the method will override the annotation on the class. Use this annotation with caution!
Old fellow iron, because of their limited personal ability, there are inevitably flaws. If you find bug or have better suggestions, please leave a message below the article.