转载

使用@async注解实现异步调用

异步调用对应的是同步调用,假设现在有三个无关任务等待执行,同步调用的方式是逐次等待,即第一个任务完成后再开始第二个任务....以此类推。

但是计算机可以并发执行,使用同步调用的耗时太长了,因此我们希望开三个县城去同时的处理这三个任务,这就需要使用@Async注解了。

如何使用@Async

在spring boot项目中使用@Async注解十分的方便。

只需要在项目启动类上添加 @EnableAsync 注解,之后在想要异步调用的方法上添加 @Async 即可。

使用实例

首先我们来看一下同步调用的结果。

在我们的测试类中添加以下三个方法。

使用@async注解实现异步调用

然后调用它。

使用@async注解实现异步调用

执行结果如下图所示:

使用@async注解实现异步调用

可以看到,三个任务是依次执行的,并且使用同一个线程调用。

总的耗时等于三个任务耗时之和。

那么异步调用呢? 首先添加一个TestService类,在该类中添加上述三个方法并且各自打上 @Async 注解。 如下图所示:

使用@async注解实现异步调用

调用它。

使用@async注解实现异步调用

得到的结果如下所示:

使用@async注解实现异步调用

可以清楚的看到,首先打印的是完成所有任务,因为只是主线程只是负责启动这三个任务,之后便输出了打印语句,而没有等到任务完成。

同时,可以清晰的看到,三个任务随机开始随机结束,且在不同的线程中运行。

@Async 注解的使用非常的简单,但是却很实用,编码过程中有许多不需要等待结果的调用(当然需要结果我们也可以通过Future拿到),这时可以使用此注解,提高总结果返回的速度。

注意事项

我在初次使用 @Async 时曾经踩过一个坑,我只注意到大佬们使用此注解却没有详细看,将 异步方法 和调用他的方法写在了同一个类里,导致异步注解没有起到效果。这里说明一下为什么。

图片转自参考链接:

使用@async注解实现异步调用

当我们给A类的b方法打上了 @Async 注解(图中为 @Transactinal ,原理同样),spring扫描到注解后,为A类创建了一个代理类proxy$A,并且给有注解的方法开始的部分添加了对应的操作,图中为 startTransaction() ,使用 @Async 时为新启动一个线程的操作(没有具体看源码)。

此时如果通过A类的实例调用a方法,在标记3的地方,之后跳转至标记1,之后调用原先的b方法,没有启动新的线程。

而通过B类的实例直接调用A类的b方法,则在标记2处,此处由spring自动添加了启动新线程的操作,因此可以实现异步调用。

完。

2018-10-29 完成

原文  https://juejin.im/post/5d2c23fb6fb9a07ecd3d8d6f
正文到此结束
Loading...