You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.
# 作用
spring容器中实现bean方法的异步调用。
比如有个logService的bean, logservice中有个log方法用来记录日志, 当调用 logService.log(msg)的时候,希望异步执行,那么可以通过 @EnableAsync & @Async 来实现。
# 用法
1. 需要异步执行的方法上面使用 @Async 注解标注, 若bean中所有的方法都需要异步执行, 可以直接将 @Async 加载类上。
2. 将 @EnableAsync 添加在spring配置类上, 此时 @Async 注解才会起效。
## 常见2种用法
1. 无返回值的
2. 可以获取返回值的
# 无返回值的
![[Snipaste_2023-02-19_15-42-08 9.png]]
# 有返回值的
![[Snipaste_2023-02-19_15-42-08 10.png]]
## 案例
![[Snipaste_2023-02-19_15-42-08 11.png]]
![[Snipaste_2023-02-19_15-42-08 12.png]]
![[Snipaste_2023-02-19_15-42-08 13.png]]
方法之间无关联的可以采用异步的方式,并行去获取,最终耗时为最长的那个方法,整体相对于同步的方式性能提升不少。
# 自定义异步执行线程池
## 方式1、在Spring容器中定义一个线程池类型的bean, bean名称必须是taskExecutor
![[Snipaste_2023-02-19_15-42-08 14.png]]
## 方式二、实现接口AsyncConfigurer
![[Snipaste_2023-02-19_15-42-08 15.png]]
# 自定义异常处理
## 异常处理分2种情况
1. 当返回值是Future的时候, 方法内部有异常的时候, 异常会向外抛出, 可以对Future.get采用try..catch来捕获异常
![[Snipaste_2023-02-19_15-42-08 16.png]]
2. 当返回值不是Future的时候, 可以自定义一个bean, 实现AsyncConfigurer接口中的getAsyncUncaughtExceptionHandler方法, 返回自定义的异常处理器
![[Snipaste_2023-02-19_16-27-02.png]]
# 线程池隔离
## 什么是线程池隔离?
一个系统中可能有很多业务,比如充值服务、提现服务或者其他服务,这些服务中都有一些方法需要异
步执行,默认情况下他们会使用同一个线程池去执行,如果有一个业务量比较大,占用了线程池中的大
量线程,此时会导致其他业务的方法无法执行,那么我们可以采用线程隔离的方式,对不同的业务使用不同的线程池,相互隔离,互不影响。@Async 注解有个 value 参数, 用来指定线程池的bean名称, 方法运行的时候, 就会采用指定的线程池来执行目标方法。
## 使用步骤
1. 在Spring容器种, 自定义线程池相关的bean
2. @Async ("线程池bean名称")
## 例
![[Snipaste_2023-02-19_16-27-02 1.png]]
![[Snipaste_2023-02-19_16-27-02 2.png]]
# 原理
内部使用aop实现的, @EnableAsync会引入一个bean后置处理器: AsyncAnnotationBeanPostProcessor , 将其注册到spring容器, 这个bean后置处理器在所有bean创建过程中, 判断bean的类上是否有@Async注解或者类中是否有@Async标注的方法, 如果有, 会通过aop给这个bean生成代理对象, 会在代理对象中添加一个切面org.springframework.scheduling.annotation.AsyncAnnotationAdvisor, 这个切面中会引入一个拦截器: AnnotationAsyncExecutionInterceptor, 方法异步调用的关键代码就是在这个拦截器的invoke方法中实现的。