The role and usage of @EnableAsync and @Async in Springboot

Refer to https://blog.csdn.net/qq_38796327/article/details/90599867

In daily development, we occasionally encounter that we need to perform multiple data operation tasks at the same time in the business layer. If we use the usual synchronization method, that is, the single-threaded method to execute, it may be caused by exceptions such as execution timeouts. The request result fails and succeeds in time, and the front end also needs to wait a long time to obtain the response result. This not only causes a poor user experience, but also often causes the problem of request execution failure.

Let's observe the results achieved by using synchronization:

1. We define a TestController as follows:

  1. @RestController

  2. public class TestController {

  3.  
  4. @Autowired

  5. private TestService service;

  6.  
  7.  
  8. /**

  9. * 使用传统方式测试

  10. */

  11. @GetMapping("/test")

  12. public void test() {

  13. System.out.println("获取主线程名称:" + Thread.currentThread().getName());

  14. service.serviceTest();

  15. System.out.println("执行成功,返回结果");

  16. }

  17. }

2. We define TestService as follows:

 
  1. @Service

  2. public class TestAsyncService {

  3.  
  4. public void serviceTest() {

  5. // 这里执行实际的业务逻辑,在这里我们就是用一个简单的遍历来模拟

  6. Arrays.stream(new int[]{1,2,3,4,5,6,7,8,9,10}).forEach( t -> {

  7. try {

  8. Thread.sleep(100);

  9. } catch (InterruptedException e) {

  10. e.printStackTrace();

  11. }

  12. System.out.println("获取number为:" + t) ;

  13. });

  14. }

  15. }

We execute the request http://localhost:8888/test, and the results are displayed as follows:

Next, we use what we call multi-threading to achieve:

1. Use thread pool to achieve

.(1) Define the test() method in TestAsyncController, as shown below:

 
  1. @RestController

  2. public class TestAsyncController {

  3.  
  4. @Autowired

  5. private TestAsyncService asyncService;

  6.  
  7. /**

  8. * 使用传统方式测试

  9. */

  10. @GetMapping("/test")

  11. public void test() {

  12. System.out.println("获取主线程名称:" + Thread.currentThread().getName());

  13. /**

  14. * 这里也可以采用以下方式使用,但是使用线程池的方式可以很便捷的对线程管理(提高程序的整体性能),

  15. * 也可以减少每次执行该请求时都需要创建一个线程造成的性能消耗

  16. * new Thread(() ->{

  17. * run方法中的业务逻辑

  18. * })

  19. */

  20.  
  21. /**

  22. * 定义一个线程池

  23. * 核心线程数(corePoolSize):1

  24. * 最大线程数(maximumPoolSize): 1

  25. * 保持连接时间(keepAliveTime):50000

  26. * 时间单位 (TimeUnit):TimeUnit.MILLISECONDS(毫秒)

  27. * 阻塞队列 new LinkedBlockingQueue<Runnable>()

  28. */

  29. ThreadPoolExecutor executor = new ThreadPoolExecutor(1,5,50000, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>());

  30. // 执行业务逻辑方法serviceTest()

  31. executor.execute(new Runnable() {

  32. @Override

  33. public void run() {

  34. asyncService.serviceTest();

  35. }

  36. });

  37. System.out.println("执行完成,向用户响应成功信息");

  38. }

  39.  
  40.  
  41. }

(2). The definition of TestAsyncService is the same as test() in TestService, which will not be displayed here;

(3). View the running results:

We found that the main thread is implemented using threads in the thread pool. The execution result of the program shows that the main thread returns the result directly, and then it is the thread pool that executes the business logic, reducing the request response time.

2. Use annotations @EnableAsync and @Async to achieve 

(1). Although this achieves the result we want, but we found that if we need this kind of asynchronous request in multiple requests, will it be possible to write such a redundant thread pool configuration every time? Of course, this problem will be Observed by our powerful spring, in order to improve the development efficiency of developers, spring uses @EnableAsync to enable asynchronous support, and @Async to perform asynchronous execution of a method. TestAsyncController looks like this:

 
  1. @RestController

  2. public class TestAsyncController {

  3.  
  4. @Autowired

  5. private TestAsyncService asyncService;

  6.  
  7. /**

  8. * 使用@Async来实现

  9. */

  10. @GetMapping("/test")

  11. public void test() {

  12. System.out.println("获取主线程名称:" + Thread.currentThread().getName());

  13. // 异步调用

  14. asyncService.serviceTest();

  15. System.out.println("执行完成,向用户响应成功信息");

  16. }

(2) TestAsyncService is as follows (refer to this for multi-threaded timing tasks):

  1. @Service

  2. @EnableAsync

  3. public class TestAsyncService {

  4.  
  5.  
  6. /**

  7. * 采用异步执行

  8. */

  9. @Async

  10. public void serviceTest() {

  11. // 这里执行实际的业务逻辑,在这里我们就是用一个简单的遍历来模拟

  12. Arrays.stream(new int[]{1,2,3,4,5,6,7,8,9,10}).forEach( t -> {

  13. try {

  14. Thread.sleep(100);

  15. } catch (InterruptedException e) {

  16. e.printStackTrace();

  17. }

  18. System.out.println("获取number为:" + t) ;

  19. });

  20. }

(3) The execution results are as follows:

The result is consistent with the result of using the thread pool, but it simplifies the logic of our code writing. The @Async annotation helps us realize the cumbersomeness of creating a thread pool and improves our development efficiency.

Guess you like

Origin blog.csdn.net/xc_nostalgia/article/details/109824704