一、背景
在日常的开发过程中,我们往往会遇到以下一些场景:当我们调用第三方接口或者方法的时候,我们不需要等待方法返回才去执行其它逻辑,这时如果响应时间过长,就会极大的影响程序的执行效率。所以这时就需要使用异步方法来并行执行我们的逻辑。同样,在执行IO操作等耗时操作时,因为比较影响客户体验和使用性能,通常情况下我们也可以使用异步方法。类似的应用还有比如发送短信、发送邮件或者消息通知等这些时效性不高的操作都可以适当的使用异步方法。
不过异步操作增加了代码的复杂性,所以我们应该谨慎使用,稍有不慎就可能产生意料之外的结果,从而影响程序的整个逻辑。
二、测试
下面我们使用一个简单的例子来看一下如何在springboot使用@Async注解实现异步操作
首先在启动类上添加 @EnableAsync 注解
TestController.java
@RestController @Slf4j public class TestController { @Autowired AsyncDemo asyncDemo; @GetMapping("/testAsync01") public void testAsync01() { asyncDemo.async01(); asyncDemo.async02(); try { log.info("start other task..."); Thread.sleep(1000); log.info("other task end..."); } catch (InterruptedException e) { e.printStackTrace(); } } }
AsyncDemo.java
/** * <p> * 测试异步方法 * </p> * * @className AsyncDemo * @author Sue * @create 2020/12/30 **/ @Slf4j @Component public class AsyncDemo { @Async public void async01() { log.info("thread{} start at{}", Thread.currentThread().getName(), System.currentTimeMillis()); try { Thread.sleep(10000); } catch (InterruptedException e) { e.printStackTrace(); } log.info("thread{} end at{}", Thread.currentThread().getName(), System.currentTimeMillis()); } @Async public void async02() { log.info("thread{} start at{}", Thread.currentThread().getName(), System.currentTimeMillis()); System.out.println(1/0); log.info("thread{} end at{}", Thread.currentThread().getName(), System.currentTimeMillis()); } }
测试,控制台输出
通过日志可以看出,方法async01和async02并没有影响后面的代码段执行,即使是方法抛出异常也不会影响其他代码的运行。说明此时,我们成功调用了异步方法。
三、补充
在使用springboot框架执行异步方法时,有以下几点需要注意
- 必须在启动类中增加@EnableAsync注解;
- 异步类没有被springboot管理,添加@Component注解(或其他注解)且保证可以扫描到异步类;
- 测试异步方法不能与异步方法在同一个类中;
- 测试类中需要使用spring容器初始化的异步类,不能自己手动new对象;
异步方法如果有返回值时,可以使用如下写法:
四、总结
这篇文章简单介绍了一下如何在springboot中使用 @Async 注解调用异步方法以及注意点,关于 @Async 注解的更多使用可以看我的另一篇文章 springboot使用@Async注解时异步方法不生效原因分析及解决方案 。