You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

README.md 6.5 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  1. ## spring-boot-demo-async
  2. > 此 demo 主要演示了 Spring Boot 如何使用原生提供的异步任务支持,实现异步执行任务。
  3. ### 1.开发步骤
  4. #### 1.1.添加依赖
  5. ```xml
  6. <dependencies>
  7. <dependency>
  8. <groupId>org.springframework.boot</groupId>
  9. <artifactId>spring-boot-starter</artifactId>
  10. </dependency>
  11. <dependency>
  12. <groupId>org.springframework.boot</groupId>
  13. <artifactId>spring-boot-starter-test</artifactId>
  14. <scope>test</scope>
  15. </dependency>
  16. <dependency>
  17. <groupId>org.projectlombok</groupId>
  18. <artifactId>lombok</artifactId>
  19. <optional>true</optional>
  20. </dependency>
  21. </dependencies>
  22. ```
  23. #### 1.2.增加异步线程池的配置
  24. > 注意:如果不配置的话,会使用默认的线程池配置
  25. ```yaml
  26. spring:
  27. task:
  28. execution:
  29. pool:
  30. # 最大线程数
  31. max-size: 16
  32. # 核心线程数
  33. core-size: 16
  34. # 存活时间
  35. keep-alive: 10s
  36. # 队列大小
  37. queue-capacity: 100
  38. # 是否允许核心线程超时
  39. allow-core-thread-timeout: true
  40. # 线程名称前缀
  41. thread-name-prefix: async-task-
  42. ```
  43. #### 1.3.同步、异步任务模拟
  44. > 1. 异步方法的返回值,需要指定为:`java.util.concurrent.Future`,`org.springframework.util.concurrent.ListenableFuture`,`java.util.concurrent.CompletableFuture`
  45. > 2. 方法上标记 `@Async`
  46. ```java
  47. @Component
  48. @Slf4j
  49. public class MockTaskFactory {
  50. /**
  51. * 模拟5秒的异步任务
  52. */
  53. @Async
  54. public CompletableFuture<Boolean> asyncTask1() throws InterruptedException {
  55. doTask("asyncTask1", 5);
  56. return CompletableFuture.completedFuture(Boolean.TRUE);
  57. }
  58. /**
  59. * 模拟2秒的异步任务
  60. */
  61. @Async
  62. public CompletableFuture<Boolean> asyncTask2() throws InterruptedException {
  63. doTask("asyncTask2", 2);
  64. return CompletableFuture.completedFuture(Boolean.TRUE);
  65. }
  66. /**
  67. * 模拟3秒的异步任务
  68. */
  69. @Async
  70. public CompletableFuture<Boolean> asyncTask3() throws InterruptedException {
  71. doTask("asyncTask3", 3);
  72. return CompletableFuture.completedFuture(Boolean.TRUE);
  73. }
  74. /**
  75. * 模拟5秒的同步任务
  76. */
  77. public void task1() throws InterruptedException {
  78. doTask("task1", 5);
  79. }
  80. /**
  81. * 模拟2秒的同步任务
  82. */
  83. public void task2() throws InterruptedException {
  84. doTask("task2", 2);
  85. }
  86. /**
  87. * 模拟3秒的同步任务
  88. */
  89. public void task3() throws InterruptedException {
  90. doTask("task3", 3);
  91. }
  92. private void doTask(String taskName, Integer time) throws InterruptedException {
  93. log.info("{}开始执行,当前线程名称【{}】", taskName, Thread.currentThread().getName());
  94. TimeUnit.SECONDS.sleep(time);
  95. log.info("{}执行成功,当前线程名称【{}】", taskName, Thread.currentThread().getName());
  96. }
  97. }
  98. ```
  99. #### 1.4.在启动类上增加注解 `@EnableAsync`
  100. ```java
  101. @EnableAsync
  102. @SpringBootApplication
  103. public class AsyncApplication {
  104. public static void main(String[] args) {
  105. SpringApplication.run(AsyncApplication.class, args);
  106. }
  107. }
  108. ```
  109. ### 2.测试
  110. #### 2.1.编写测试代码
  111. ```java
  112. @Slf4j
  113. @SpringBootTest
  114. @DisplayName("异步化测试")
  115. public class MockTaskFactoryTest {
  116. @Autowired
  117. private MockTaskFactory task;
  118. /**
  119. * 测试异步任务
  120. */
  121. @Test
  122. @DisplayName("异步任务")
  123. public void asyncTaskTest() throws InterruptedException, ExecutionException {
  124. long start = System.currentTimeMillis();
  125. CompletableFuture<Boolean> asyncResult1 = task.asyncTask1();
  126. CompletableFuture<Boolean> asyncResult2 = task.asyncTask2();
  127. CompletableFuture<Boolean> asyncResult3 = task.asyncTask3();
  128. CompletableFuture<Void> allResult = CompletableFuture.allOf(asyncResult1, asyncResult2, asyncResult3);
  129. // 调用 get() 阻塞主线程
  130. allResult.get();
  131. long end = System.currentTimeMillis();
  132. log.info("异步任务全部执行结束,总耗时:{} 毫秒", (end - start));
  133. }
  134. /**
  135. * 测试同步任务
  136. */
  137. @Test
  138. @DisplayName("同步任务")
  139. public void taskTest() throws InterruptedException {
  140. long start = System.currentTimeMillis();
  141. task.task1();
  142. task.task2();
  143. task.task3();
  144. long end = System.currentTimeMillis();
  145. log.info("同步任务全部执行结束,总耗时:{} 毫秒", (end - start));
  146. }
  147. }
  148. ```
  149. #### 2.2运行结果
  150. - 异步任务
  151. ```bash
  152. INFO 11574 --- [ async-task-1] com.xkcoding.async.task.MockTaskFactory : asyncTask1开始执行,当前线程名称【async-task-1】
  153. INFO 11574 --- [ async-task-2] com.xkcoding.async.task.MockTaskFactory : asyncTask2开始执行,当前线程名称【async-task-2】
  154. INFO 11574 --- [ async-task-3] com.xkcoding.async.task.MockTaskFactory : asyncTask3开始执行,当前线程名称【async-task-3】
  155. INFO 11574 --- [ async-task-2] com.xkcoding.async.task.MockTaskFactory : asyncTask2执行成功,当前线程名称【async-task-2】
  156. INFO 11574 --- [ async-task-3] com.xkcoding.async.task.MockTaskFactory : asyncTask3执行成功,当前线程名称【async-task-3】
  157. INFO 11574 --- [ async-task-1] com.xkcoding.async.task.MockTaskFactory : asyncTask1执行成功,当前线程名称【async-task-1】
  158. INFO 11574 --- [ main] c.x.async.task.MockTaskFactoryTest : 异步任务全部执行结束,总耗时:5017 毫秒
  159. ```
  160. - 同步任务
  161. ```bash
  162. INFO 11574 --- [ main] com.xkcoding.async.task.MockTaskFactory : task1开始执行,当前线程名称【main】
  163. INFO 11574 --- [ main] com.xkcoding.async.task.MockTaskFactory : task1执行成功,当前线程名称【main】
  164. INFO 11574 --- [ main] com.xkcoding.async.task.MockTaskFactory : task2开始执行,当前线程名称【main】
  165. INFO 11574 --- [ main] com.xkcoding.async.task.MockTaskFactory : task2执行成功,当前线程名称【main】
  166. INFO 11574 --- [ main] com.xkcoding.async.task.MockTaskFactory : task3开始执行,当前线程名称【main】
  167. INFO 11574 --- [ main] com.xkcoding.async.task.MockTaskFactory : task3执行成功,当前线程名称【main】
  168. INFO 11574 --- [ main] c.x.async.task.MockTaskFactoryTest : 同步任务全部执行结束,总耗时:10032 毫秒
  169. ```
  170. ### 3.参考
  171. - Spring Boot 异步任务线程池的配置 参考官方文档:https://docs.spring.io/spring-boot/docs/3.0.0-M4/reference/htmlsingle/#features.task-execution-and-scheduling