在使用异步注解之前,我们需要先了解,什么是异步调用?
异步调用对应的事同步调用,同步调用是值程序按照我们定义的顺序依次执行,每一行程序都必须等待上一行的程序执行完成之后才执行,而异步是指在顺序执行的时候,不等待异步调用的语句返回结果就执行后面的程序,例如,我们常常进行对报表的导出,因为数据导出需要时间,为了避免用户在界面等待时间过长,我们就会采用异步进行导出。
我们来对比一下同步导出和异步导出的案例:
@Slf4j
@Component
public class AsyncTasks {
public static Random random = new Random();
//@Async
public CompletableFuture<String> doTaskOne() throws Exception {
log.info("开始做任务一");
long start = System.currentTimeMillis();
Thread.sleep(random.nextInt(10000));
long end = System.currentTimeMillis();
log.info("完成任务一,耗时:" + (end - start) + "毫秒");
return CompletableFuture.completedFuture("任务一完成");
}
//@Async
public CompletableFuture<String> doTaskTwo() throws Exception {
log.info("开始做任务二");
long start = System.currentTimeMillis();
Thread.sleep(random.nextInt(10000));
long end = System.currentTimeMillis();
log.info("完成任务二,耗时:" + (end - start) + "毫秒");
return CompletableFuture.completedFuture("任务二完成");
}
//@Async
public CompletableFuture<String> doTaskThree() throws Exception {
log.info("开始做任务三");
long start = System.currentTimeMillis();
Thread.sleep(random.nextInt(10000));
long end = System.currentTimeMillis();
log.info("完成任务三,耗时:" + (end - start) + "毫秒");
return CompletableFuture.completedFuture("任务三完成");
}
}
在我们的测试类中执行三个函数方法,
@Slf4j
@SpringBootTest
public class ApplicationTests {
@Autowired
private AsyncTasks asyncTasks;
@Test
public void test() throws Exception {
asyncTasks.doTaskOne();
asyncTasks.doTaskTwo();
asyncTasks.doTaskThree();
}
}
异步调用:
@Slf4j
@Component
public class AsyncTasks {
public static Random random = new Random();
@Async
public CompletableFuture<String> doTaskOne() throws Exception {
log.info("开始做任务一");
long start = System.currentTimeMillis();
Thread.sleep(random.nextInt(10000));
long end = System.currentTimeMillis();
log.info("完成任务一,耗时:" + (end - start) + "毫秒");
return CompletableFuture.completedFuture("任务一完成");
}
@Async
public CompletableFuture<String> doTaskTwo() throws Exception {
log.info("开始做任务二");
long start = System.currentTimeMillis();
Thread.sleep(random.nextInt(10000));
long end = System.currentTimeMillis();
log.info("完成任务二,耗时:" + (end - start) + "毫秒");
return CompletableFuture.completedFuture("任务二完成");
}
@Async
public CompletableFuture<String> doTaskThree() throws Exception {
log.info("开始做任务三");
long start = System.currentTimeMillis();
Thread.sleep(random.nextInt(10000));
long end = System.currentTimeMillis();
log.info("完成任务三,耗时:" + (end - start) + "毫秒");
return CompletableFuture.completedFuture("任务三完成");
}
}
@Slf4j
@SpringBootTest
public class ApplicationTests {
@Autowired
private AsyncTasks asyncTasks;
@Test
public void test() throws Exception {
long start = System.currentTimeMillis();
CompletableFuture<String> task1 = asyncTasks.doTaskOne();
CompletableFuture<String> task2 = asyncTasks.doTaskTwo();
CompletableFuture<String> task3 = asyncTasks.doTaskThree();
CompletableFuture.allOf(task1, task2, task3).join();
long end = System.currentTimeMillis();
log.info("任务全部完成,总耗时:" + (end - start) + "毫秒");
}
}
注意,异步调用的结果是随机的,你的结果和我这边的结果不一样很正常。