1、场景描述
我们在开发的过程中,可能会遇见如下场景:
一个业务A,这个A业务中包含了4个小业务,分别是a,b,c,d。在实际操作中,有时候第三个业务c,执行的时间比较长或者c业务是属于其他系统的api调用。这个时候,我们就期望a,c,d三个也是先执行完毕,然后提示用户业务成功。而不必等待c业务结束后,在提示用户。这样的好处是,能够实现业务分离,且用户体验较好。
常见的应用场景:如短信方法,订单提交,邮件发送,消息推送等。
常见的解决办法:
第一种:可以通过RabbitMQ\ActiveMQ\KAFKA等消息中间件实现
第二种:可以通过@Async注解实现
总结:
如果调用的服务涉及到其他系统建议使用消息中间件
如果调用的服务都在一个工程中,建议使用@Async注解,足够使用。
@Async使用注意点
1、被@Async修饰的方法,需要单独写在一个独立的类中,不能与当前业务在同一个类中。
2、使用的时候需要再启动类中启动异步任务,@EnableAsync
3、被@Async注解修饰的方法,会运行在一个独立的线程中,调用者无需等待它的完成。
2、@Async实现异步调用方式
2.1、创建sprigboot工程
我使用的springboot是3.1.6版本,同时选择了springboot-web开发,包信息如下
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.1.6</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.txc</groupId>
<artifactId>asynctaskdemo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>asynctaskdemo</name>
<description>asynctaskdemo</description>
<properties>
<java.version>17</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<image>
<builder>paketobuildpacks/builder-jammy-base:latest</builder>
</image>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</project>
2.2、在启动类中开启异步任务
@EnableAsync//开启异步任务
@SpringBootApplication
public class SpringbootAsyncApplication {
public static void main(String[] args) {
SpringApplication.run(SpringbootAsyncApplication.class, args);
}
}
2.3、创建StudentAsyncService业务类
说明1:@Async注解写在类上,表示所有方法都异步执行,写在方法上表示某一个方法异步执行
说明2:StudentAsyncService需要被spring扫描到,如果是业务层使用@Service,其他地方使用@Component注解。
@Service
public class StudentAsyncService {
@Async//那个方法需要使用异步调用,就使用该注解
public void asyncMethod(String data) {
try{
Thread.sleep(6000);//模拟异步执行业务的时间
}catch (Exception e){
System.out.println(e.getStackTrace());
}
System.out.println("=======异步线程执行结束========");
}
}
2.4、创建控制层类调用service异步方法
@Controller
public class StudentController {
@Autowired
private StudentAsyncService studentAsyncService;
@RequestMapping("/testMethod")
public String testMethod(){
System.out.println("======主线程开始执行======");
studentAsyncService.asyncMethod("你要传递的数据");//异步执行方法
System.out.println("======主线程结束执行======");
return "index";//返回的视图逻辑地址
}
}
2.5、测试结果
访问地址:http://localhost:8080/testMethod
通过结果我们可以看出,主线程任务有限执行结束,6秒后异步代码执行结束。