异步调用对应的是同步调用,假设现在有三个无关任务等待执行,同步调用的方式是逐次等待,即第一个任务完成后再开始第二个任务....以此类推。
但是计算机可以并发执行,使用同步调用的耗时太长了,因此我们希望开三个县城去同时的处理这三个任务,这就需要使用@Async注解了。
在spring boot项目中使用@Async注解十分的方便。
只需要在项目启动类上添加 @EnableAsync
注解,之后在想要异步调用的方法上添加 @Async
即可。
首先我们来看一下同步调用的结果。
在我们的测试类中添加以下三个方法。
然后调用它。
执行结果如下图所示:
可以看到,三个任务是依次执行的,并且使用同一个线程调用。
总的耗时等于三个任务耗时之和。
那么异步调用呢? 首先添加一个TestService类,在该类中添加上述三个方法并且各自打上 @Async
注解。 如下图所示:
调用它。
得到的结果如下所示:
可以清楚的看到,首先打印的是完成所有任务,因为只是主线程只是负责启动这三个任务,之后便输出了打印语句,而没有等到任务完成。
同时,可以清晰的看到,三个任务随机开始随机结束,且在不同的线程中运行。
@Async
注解的使用非常的简单,但是却很实用,编码过程中有许多不需要等待结果的调用(当然需要结果我们也可以通过Future拿到),这时可以使用此注解,提高总结果返回的速度。
我在初次使用 @Async
时曾经踩过一个坑,我只注意到大佬们使用此注解却没有详细看,将 异步方法 和调用他的方法写在了同一个类里,导致异步注解没有起到效果。这里说明一下为什么。
图片转自参考链接:
当我们给A类的b方法打上了 @Async
注解(图中为 @Transactinal
,原理同样),spring扫描到注解后,为A类创建了一个代理类proxy$A,并且给有注解的方法开始的部分添加了对应的操作,图中为 startTransaction()
,使用 @Async
时为新启动一个线程的操作(没有具体看源码)。
此时如果通过A类的实例调用a方法,在标记3的地方,之后跳转至标记1,之后调用原先的b方法,没有启动新的线程。
而通过B类的实例直接调用A类的b方法,则在标记2处,此处由spring自动添加了启动新线程的操作,因此可以实现异步调用。
完。2018-10-29 完成