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

SpringBoot使用JNA调用dll springboot 调用方法_maven

 通过结果我们可以看出,主线程任务有限执行结束,6秒后异步代码执行结束。