概述
@Async 是Spring提供的一种用于实现异步执行的注解,常用于解决IO密集型任务,如:数据库查询、文件读写、远程服务调用等。
案例
引入maven依赖
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<version>2.5.4</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>2.5.4</version>
</dependency>
<!-- 方便等会写单元测试 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<version>2.5.4</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</dependency>
</dependencies>
启动类上加@EnableAsync
package com.shiqitool.async;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableAsync;
/**
* @program: shiqitool
* @description:
* @author: shiqi
* @create: 2024-09-05 16:57
**/
@SpringBootApplication
@EnableAsync
public class AsyncApplication {
public static void main(String[] args) {
SpringApplication.run(AsyncApplication.class, args);
}
}
测试同步
private Logger logger = LoggerFactory.getLogger(getClass());
/**
* 同步业务1
* @return
*/
public Integer businessSync1() {
logger.info("[businessSync1]");
sleep(10);
return 1;
}
/**
* 同步业务2
* @return
*/
public Integer businessSync2() {
logger.info("[businessSync2]");
sleep(5);
return 2;
}
private static void sleep(int seconds) {
try {
Thread.sleep(seconds * 1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
private Logger logger = LoggerFactory.getLogger(getClass());
@Autowired
private AsyncBusinessService asyncBusinessService;
@Test
public void taskSync() {
long now = System.currentTimeMillis();
logger.info("[taskSync][开始执行]");
asyncBusinessService.businessSync1();
asyncBusinessService.businessSync2();
logger.info("[taskSync][结束执行,消耗时长 {} 毫秒]", System.currentTimeMillis() - now);
}
结果
2024-09-06 23:04:47.026 INFO 28224 --- [ main] c.s.a.service.AsyncBusinessServiceTest : [taskSync][开始执行]
2024-09-06 23:04:47.044 INFO 28224 --- [ main] c.s.async.service.AsyncBusinessService : [businessSync1]
2024-09-06 23:04:57.046 INFO 28224 --- [ main] c.s.async.service.AsyncBusinessService : [businessSync2]
2024-09-06 23:05:02.056 INFO 28224 --- [ main] c.s.a.service.AsyncBusinessServiceTest : [taskSync][结束执行,消耗时长 15030 毫秒]
结论
15秒执行完成,程序退出
测试异步
/**
* 异步业务1
* @return
*/
@Async
public Integer businessAsync1() {
logger.info("[businessAsync1]");
sleep(10);
return 1;
}
/**
* 异步业务2
* @return
*/
@Async
public Integer businessAsync2() {
logger.info("[businessAsync2]");
sleep(5);
return 2;
}
@Test
public void taskAsync() {
long now = System.currentTimeMillis();
logger.info("[taskAsync][开始执行]");
asyncBusinessService.businessAsync1();
asyncBusinessService.businessAsync2();
logger.info("[taskAsync][结束执行,消耗时长 {} 毫秒]", System.currentTimeMillis() - now);
}
结果
2024-09-06 23:07:46.374 INFO 5388 --- [ main] c.s.a.service.AsyncBusinessServiceTest : [taskAsync][开始执行]
2024-09-06 23:07:46.383 INFO 5388 --- [ main] c.s.a.service.AsyncBusinessServiceTest : [taskAsync][结束执行,消耗时长 9 毫秒]
2024-09-06 23:07:46.397 INFO 5388 --- [ async-task-1] c.s.async.service.AsyncBusinessService : [businessAsync1]
2024-09-06 23:07:46.397 INFO 5388 --- [ async-task-2] c.s.async.service.AsyncBusinessService : [businessAsync2]
2024-09-06 23:07:46.466 WARN 5388 --- [ionShutdownHook] o.s.s.concurrent.ThreadPoolTaskExecutor : Timed out while waiting for executor 'applicationTaskExecutor' to terminate
结论
异步不等待结果返回,主线程直接退出
测试异步等待结果返回
/**
* 等待返回结果1
* @return
*/
@Async
public Future<Integer> businessAsyncWithFuture1() {
return AsyncResult.forValue(this.businessSync1());
}
/**
* 等待返回结果2
* @return
*/
@Async
public Future<Integer> businessAsyncWithFuture2() {
return AsyncResult.forValue(this.businessSync2());
}
@Test
public void taskAsyncFuture() throws ExecutionException, InterruptedException {
long now = System.currentTimeMillis();
logger.info("[taskAsyncFuture][开始执行]");
Future<Integer> future1 = asyncBusinessService.businessAsyncWithFuture1();
Future<Integer> future2 = asyncBusinessService.businessAsyncWithFuture2();
future1.get();
future2.get();
logger.info("[taskAsyncFuture][结束执行,消耗时长 {} 毫秒]", System.currentTimeMillis() - now);
}
结果
2024-09-06 23:10:06.618 INFO 30512 --- [ main] c.s.a.service.AsyncBusinessServiceTest : [taskAsyncFuture][开始执行]
2024-09-06 23:10:06.639 INFO 30512 --- [ async-task-1] c.s.async.service.AsyncBusinessService : [businessSync1]
2024-09-06 23:10:06.639 INFO 30512 --- [ async-task-2] c.s.async.service.AsyncBusinessService : [businessSync2]
2024-09-06 23:10:16.640 INFO 30512 --- [ main] c.s.a.service.AsyncBusinessServiceTest : [taskAsyncFuture][结束执行,消耗时长 10022 毫秒]
结论
等待最长的线程执行解释,10秒