什么是“异步调用”?“异步调用”对应“同步调用”。同步调用是指程序按照定义好的顺序依次执行。每行程序必须等待上一行程序执行完成后才能执行;异步调用是指程序在顺序执行时不等待异步调用。如果语句返回结果,将执行下面的程序。同步调用下面通过一个简单的例子来直观的理解什么是同步调用:定义Task类,创建三个处理函数模拟执行任务的三个操作,操作时间随机选择(10秒以内)@Slf4j@Componentpublic类AsyncTasks{publicstaticRandomrandom=newRandom();publicvoiddoTaskOne()throwsException{log.info("开始任务一");长启动=System.currentTimeMillis();Thread.sleep(random.nextInt(10000));长端=System.currentTimeMillis();log.info("完成任务一的时间:"+(end-start)+"milliseconds");}publicvoiddoTaskTwo()throwsException{log.info("开始做任务二");长启动=System.currentTimeMillis();Thread.sleep(random.nextInt(10000));长端=System.currentTimeMillis();log.info("完成任务二,耗时:"+(end-start)+"毫秒");}publicvoiddoTaskThree()throwsException{log.info("开始做任务三");长启动=System.currentTimeMillis();Thread.sleep(random.nextInt(10000));长端=System.currentTimeMillis();log.info("完成任务三,耗时:"+(end-start)+"milliseconds");}}在单元测试用例中,注入Task对象,执行测试用例中的三个函数doTaskOne、doTaskTwo、doTaskThree@Slf4j@SpringBootTest公共类Chapter75ApplicationTests{@AutowiredprivateAsyncTasksasyncTasks;@Testpublicvoidtest()throwsException{asyncTasks.doTaskOne();asyncTasks.doTaskTwo();asyncTasks.doTaskThree();输出类似如下:2021-09-1123:19:12.922INFO92539---[main]com.didispace.chapter75.AsyncTasks:starttaskone2021-09-1123:19:17.788INFO92539---[main]com.didispace.chapter75.AsyncTasks:完成任务1,耗时:4865毫秒2021-09-1123:19:17.788INFO92539---[main]com.didispace.chapter75.AsyncTasks:开始任务22021-09-1123:19:24.851INFO92539---[main]com.didispace.chapter75.AsyncTasks:完成任务二,耗时:7063毫秒2021-09-1123:19:24.851INFO92539---[main]com.didispace.chapter75.AsyncTasks:Starttask32021-09-1123:19:26.928INFO92539---[main]com.didispace.chapter75.AsyncTasks:完成任务3,耗时:2076毫秒任务1.任务2,任务3序列也就是说,依次执行doTaskOne、doTaskTwo、doTaskThree这三个函数,完成异步调用。上面的同步调用虽然成功执行了三个任务,但是可以看出执行时间比较长。如果存在依赖关系,可以并发执行,同步调用的执行效率比较差,可以考虑异步调用并发执行。在SpringBoot中,我们只需要使用@Async注解,就可以简单的把原来的同步函数变成异步函数,Task类改为如下模式:@Slf4j@ComponentpublicclassAsyncTasks{publicstaticRandomrandom=newRandom();@AsyncpublicvoiddoTaskOne()throwsException{log.info("开始任务一");长启动=System.currentTimeMillis();Thread.sleep(random.nextInt(10000));长端=系统。当前时间毫秒();log.info("完成任务一的时间:"+(end-start)+"milliseconds");}@AsyncpublicvoiddoTaskTwo()throwsException{log.info("开始任务二");长启动=System.currentTimeMillis();Thread.sleep(random.nextInt(10000));长端=System.currentTimeMillis();log.info("完成任务二,耗时:"+(end-start)+"毫秒");}@AsyncpublicvoiddoTaskThree()throwsException{log.info("开始做任务三");长启动=System.currentTimeMillis();Thread.sleep(random.nextInt(10000));长端=System.currentTimeMillis();log.info("完成任务三,耗时:"+(end-start)+"milliseconds");}}为了让@Async注解生效,还需要在SpringBoot的主程序中配置@EnableAsync,如下:@EnableAsync@SpringBootApplicationpublicclassChapter75Application{publicstaticvoidmain(String[]args){SpringApplication.run(Chapter75Application.class,args);}}此时可以反复执行单元测试,可能会遇到各种结果,比如:notask-relatedoutputwithpartial任务相关输出乱序的原因是doTaskOne,doTaskTwo,doTaskThree这三个函数已经被异步执行过,异步调用后,主程序并不关心这三个函数是否执行functions完成后,由于没有其他内容需要执行,程序自动结束,导致任务相关内容不完整或者没有输出。注意:@Async修饰的函数不要定义为static类型,这样异步调用不会生效异步回调为了让doTaskOne、doTaskTwo、doTaskThree正常结束,假设我们需要统计这三个任务并发执行的总耗时。这就需要把上面三个函数全部调完后,记录时间,计算结果。那么我们如何判断以上三个异步调用是否已经执行呢?我们需要使用CompletableFuture
