SpringBoot使用@Async实现异步调用

概念
  • 同步调用:同步调用指程序按照定义顺序依次执行,每一行程序都必须等待上一行程序执行完成之后才能执行;
  • 异步调用:异步调用指程序在顺序执行时,不等待异步调用的语句返回结果就执行后面的程序。
异步调用
  • 在Spring Boot中,可以通过使用@Async注解就能简单的将原来的同步函数变为异步函数;
  • 主程序在异步调用之后,主程序并不会理会异步函数是否执行完成了,由于没有其他需要执行的内容,所以程序就自动结束了,导致了不完整或是没有输出任务相关内容的情况。
异步回调
  • 为了让异步函数都能正常结束,我们需要判断异步调用是否以及执行完成,可以使用Future<T>来返回异步调用的结果。示例如下:
@Component
public class Task {
    public static Random random =new Random();

    @Async
    public Future<String> doTaskOne() throws Exception {
        System.out.println("开始做任务一");
        long start = System.currentTimeMillis();
        Thread.sleep(random.nextInt(10000));
        long end = System.currentTimeMillis();
        System.out.println("完成任务一,耗时:" + (end - start) + "毫秒");
        return new AsyncResult<>("任务一完成");
    }

    @Async
    public Future<String> doTaskTwo() throws Exception {
        System.out.println("开始做任务二");
        long start = System.currentTimeMillis();
        Thread.sleep(random.nextInt(10000));
        long end = System.currentTimeMillis();
        System.out.println("完成任务二,耗时:" + (end - start) + "毫秒");
        return new AsyncResult<>("任务二完成");
    }

    @Async
    public Future<String> doTaskThree() throws Exception {
        System.out.println("开始做任务三");
        long start = System.currentTimeMillis();
        Thread.sleep(random.nextInt(10000));
        long end = System.currentTimeMillis();
        System.out.println("完成任务三,耗时:" + (end - start) + "毫秒");
        return new AsyncResult<>("任务三完成");
    }
}

注:@Async所修饰的函数不要定义为static类型,这样异步调用不会生效

  • 为了让@Async注解能够生效,还需在Spring Boot的主程序中配置@EnableAsync,如下:
@SpringBootApplication
@EnableAsync
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}
  • 测试用例
@Test
public void test() throws Exception {

    long start = System.currentTimeMillis();

    Future<String> task1 = task.doTaskOne();
    Future<String> task2 = task.doTaskTwo();
    Future<String> task3 = task.doTaskThree();

    while(true) {
        if(task1.isDone() && task2.isDone() && task3.isDone()) {
            // 三个任务都调用完成,退出循环等待
            break;
        }
        Thread.sleep(1000);
    }
    long end = System.currentTimeMillis();
    System.out.println("任务全部完成,总耗时:" + (end - start) + "毫秒");

}
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容