|
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209 |
- ## spring-boot-demo-async
-
- > 此 demo 主要演示了 Spring Boot 如何使用原生提供的异步任务支持,实现异步执行任务。
-
- ### 1.开发步骤
-
- #### 1.1.添加依赖
-
- ```xml
- <dependencies>
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter</artifactId>
- </dependency>
-
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-test</artifactId>
- <scope>test</scope>
- </dependency>
-
- <dependency>
- <groupId>org.projectlombok</groupId>
- <artifactId>lombok</artifactId>
- <optional>true</optional>
- </dependency>
- </dependencies>
- ```
-
- #### 1.2.增加异步线程池的配置
-
- > 注意:如果不配置的话,会使用默认的线程池配置
-
- ```yaml
- spring:
- task:
- execution:
- pool:
- # 最大线程数
- max-size: 16
- # 核心线程数
- core-size: 16
- # 存活时间
- keep-alive: 10s
- # 队列大小
- queue-capacity: 100
- # 是否允许核心线程超时
- allow-core-thread-timeout: true
- # 线程名称前缀
- thread-name-prefix: async-task-
- ```
-
- #### 1.3.同步、异步任务模拟
-
- > 1. 异步方法的返回值,需要指定为:`java.util.concurrent.Future`,`org.springframework.util.concurrent.ListenableFuture`,`java.util.concurrent.CompletableFuture`
- > 2. 方法上标记 `@Async`
-
- ```java
- @Component
- @Slf4j
- public class MockTaskFactory {
-
- /**
- * 模拟5秒的异步任务
- */
- @Async
- public CompletableFuture<Boolean> asyncTask1() throws InterruptedException {
- doTask("asyncTask1", 5);
- return CompletableFuture.completedFuture(Boolean.TRUE);
- }
-
- /**
- * 模拟2秒的异步任务
- */
- @Async
- public CompletableFuture<Boolean> asyncTask2() throws InterruptedException {
- doTask("asyncTask2", 2);
- return CompletableFuture.completedFuture(Boolean.TRUE);
- }
-
- /**
- * 模拟3秒的异步任务
- */
- @Async
- public CompletableFuture<Boolean> asyncTask3() throws InterruptedException {
- doTask("asyncTask3", 3);
- return CompletableFuture.completedFuture(Boolean.TRUE);
- }
-
- /**
- * 模拟5秒的同步任务
- */
- public void task1() throws InterruptedException {
- doTask("task1", 5);
- }
-
- /**
- * 模拟2秒的同步任务
- */
- public void task2() throws InterruptedException {
- doTask("task2", 2);
- }
-
- /**
- * 模拟3秒的同步任务
- */
- public void task3() throws InterruptedException {
- doTask("task3", 3);
- }
-
- private void doTask(String taskName, Integer time) throws InterruptedException {
- log.info("{}开始执行,当前线程名称【{}】", taskName, Thread.currentThread().getName());
- TimeUnit.SECONDS.sleep(time);
- log.info("{}执行成功,当前线程名称【{}】", taskName, Thread.currentThread().getName());
- }
- }
- ```
-
- #### 1.4.在启动类上增加注解 `@EnableAsync`
-
- ```java
- @EnableAsync
- @SpringBootApplication
- public class AsyncApplication {
-
- public static void main(String[] args) {
- SpringApplication.run(AsyncApplication.class, args);
- }
-
- }
- ```
-
- ### 2.测试
-
- #### 2.1.编写测试代码
-
- ```java
- @Slf4j
- @SpringBootTest
- @DisplayName("异步化测试")
- public class MockTaskFactoryTest {
- @Autowired
- private MockTaskFactory task;
-
- /**
- * 测试异步任务
- */
- @Test
- @DisplayName("异步任务")
- public void asyncTaskTest() throws InterruptedException, ExecutionException {
- long start = System.currentTimeMillis();
- CompletableFuture<Boolean> asyncResult1 = task.asyncTask1();
- CompletableFuture<Boolean> asyncResult2 = task.asyncTask2();
- CompletableFuture<Boolean> asyncResult3 = task.asyncTask3();
-
- CompletableFuture<Void> allResult = CompletableFuture.allOf(asyncResult1, asyncResult2, asyncResult3);
- // 调用 get() 阻塞主线程
- allResult.get();
- long end = System.currentTimeMillis();
-
- log.info("异步任务全部执行结束,总耗时:{} 毫秒", (end - start));
- }
-
- /**
- * 测试同步任务
- */
- @Test
- @DisplayName("同步任务")
- public void taskTest() throws InterruptedException {
- long start = System.currentTimeMillis();
- task.task1();
- task.task2();
- task.task3();
- long end = System.currentTimeMillis();
-
- log.info("同步任务全部执行结束,总耗时:{} 毫秒", (end - start));
- }
- }
- ```
-
- #### 2.2运行结果
-
- - 异步任务
-
- ```bash
- INFO 11574 --- [ async-task-1] com.xkcoding.async.task.MockTaskFactory : asyncTask1开始执行,当前线程名称【async-task-1】
- INFO 11574 --- [ async-task-2] com.xkcoding.async.task.MockTaskFactory : asyncTask2开始执行,当前线程名称【async-task-2】
- INFO 11574 --- [ async-task-3] com.xkcoding.async.task.MockTaskFactory : asyncTask3开始执行,当前线程名称【async-task-3】
- INFO 11574 --- [ async-task-2] com.xkcoding.async.task.MockTaskFactory : asyncTask2执行成功,当前线程名称【async-task-2】
- INFO 11574 --- [ async-task-3] com.xkcoding.async.task.MockTaskFactory : asyncTask3执行成功,当前线程名称【async-task-3】
- INFO 11574 --- [ async-task-1] com.xkcoding.async.task.MockTaskFactory : asyncTask1执行成功,当前线程名称【async-task-1】
- INFO 11574 --- [ main] c.x.async.task.MockTaskFactoryTest : 异步任务全部执行结束,总耗时:5017 毫秒
- ```
-
- - 同步任务
-
- ```bash
- INFO 11574 --- [ main] com.xkcoding.async.task.MockTaskFactory : task1开始执行,当前线程名称【main】
- INFO 11574 --- [ main] com.xkcoding.async.task.MockTaskFactory : task1执行成功,当前线程名称【main】
- INFO 11574 --- [ main] com.xkcoding.async.task.MockTaskFactory : task2开始执行,当前线程名称【main】
- INFO 11574 --- [ main] com.xkcoding.async.task.MockTaskFactory : task2执行成功,当前线程名称【main】
- INFO 11574 --- [ main] com.xkcoding.async.task.MockTaskFactory : task3开始执行,当前线程名称【main】
- INFO 11574 --- [ main] com.xkcoding.async.task.MockTaskFactory : task3执行成功,当前线程名称【main】
- INFO 11574 --- [ main] c.x.async.task.MockTaskFactoryTest : 同步任务全部执行结束,总耗时:10032 毫秒
- ```
-
- ### 3.参考
-
- - Spring Boot 异步任务线程池的配置 参考官方文档:https://docs.spring.io/spring-boot/docs/3.0.0-M4/reference/htmlsingle/#features.task-execution-and-scheduling
|