最近在新入职的一家公司的开发中,遇到一个这样的场景,有一个催单的小功能,客户在定完餐后半个小时之后可以进行催单,我们当时的逻辑是客户每催单一次,就会向公司的运营人员的企业微信发送一条消息并向前端返回一个催单间隔时间。
依照我刚开始进入公司的编码习惯,我肯定会先发送消息,后面再向数据库中存储数据,这种顺序执行。对于有过项目经验的人来说,一定会使用异步的方法来提高程序的性能。为什么呢?因为在调用第三方接口的时候,可能会存在各种情况,例如,消息发送由于网络原因导致失败或者超时,这个时候我们的异步方法显得尤为重要。
异步方法使用的场景:在项目中,当访问其他人的接口较慢或者做耗时任务时,不想程序一直卡在耗时任务上,想程序能够并行执行,我们可以使用多线程来并行的处理任务,也可以使用spring提供的异步处理方式@Async。例如,发送短息、发送邮件,APP消息推送等。
下面是我写的一个异步方法的小demo
启动类上面首先要加上注解@EnableAsync
package com.xzz.service.sale; import
org.springframework.boot.SpringApplication; import
org.springframework.boot.autoconfigure.SpringBootApplication; import
org.springframework.scheduling.annotation.EnableAsync; @SpringBootApplication
@EnableAsync public class ServiceSaleApplication { public static void
main(String[] args) { SpringApplication.run(ServiceSaleApplication.class,
args); } }
异步方法类
package com.xzz.service.sale.mytest; import lombok.extern.slf4j.Slf4j; import
org.springframework.scheduling.annotation.Async; import
org.springframework.stereotype.Component; @Component @Slf4j public class
TestAnysc { @Async public void dealNoReturnTask(){ log.info("Thread {} deal No
Return Task start", Thread.currentThread().getName()); try {
Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); }
log.info("Thread {} deal No Return Task end at {}",
Thread.currentThread().getName(), System.currentTimeMillis()); } }
测试类
/** * 测试@Async异步 * */ @Autowired TestAnysc testAnysc; @Test public void
testDealNoReturnTask(){ testAnysc.dealNoReturnTask(); try { log.info("begin to
deal other Task!"); Thread.sleep(10000); } catch (InterruptedException e) {
e.printStackTrace(); } }
测试的结果
begin to deal other Task! Thread {} deal No Return Task start Thread {} deal
No Return Task end at {}
结果证明我们成功了。
接下来我总结了一下,我在使用@Async踩过的坑
异步类没有使用@Component注解(或其他注解)导致spring无法扫描到异步类;
测试异步方法不能与异步方法在同一个类中;
测试类中需要使用@Autowired或@Resource等注解自动注入,不能自己手动new对象;
如果使用SpringBoot框架必须在启动类中增加@EnableAsync注解。