在接口调用时,如果执行的时间长,那么为了提升响应时间,通常是先立即响应,然后再异步执行业务逻辑。
那么在平时处理时就可以用@Async注解。使用@Async时,会在调用时新开启一个线程来跑任务。
但是在使用时会遇到注解@Async不生效的问题,下面来分析造成的原因。
使用@Async的代码
Controller类
@RestController
@Slf4j
public class AsyncControllerDemo {
@Autowired
private AsyncServiceDemo asyncServiceDemo;
@GetMapping("/test/async")
public String testAsync(){
log.info(this.getClass().getSimpleName() + " testAsync starts");
asyncServiceDemo.testAsyncService();
log.info(this.getClass().getSimpleName() + " testAsync ends");
return "success";
}
}
Service类
@Service
@Slf4j
public class AsyncServiceDemo {
@Async
public void testAsyncService(){
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
log.error("e",e);
}
log.info(this.getClass().getSimpleName() + " testAsyncService ends");
}
}
启动程序
启动程序后,在浏览器调用接口。
但是实际并没有想象中的异步处理:可以通过耗时10s、线程号和输出日志都可以看出来。
相当于程序仍然是同步的调用,异步注解@Async并没有生效。
@Async什么情况下不生效
启动类未使用@EnableAsync注解
@EnableAsync注解使用来开启异步线程的,使@Aysnc生效。
那么在这个项目中就是因为启动类没有加启动类@EnableAsync导致的。
调整以后,从线程号和打印的日志可以看出:@Async生效后,接口先响应,后执行异步的方法。
同一个类中调用含@Async的方法
在同一个类中A方法调用B方法也是不生效的。
@Async为何不生效
具体原因需要继续探究,了解深层源码中关于aop的内容。
源码分析可学习了解以下文章:
异步任务spring @Async注解源码解析:https://www.cnblogs.com/dennyzhangdd/p/9026303.html