@Async 多线程 使用注意点

因为在实际业务开发中像循环依赖、类内方法调用(会引起@Async不生效)等情况并不能避免 

异步方法和调用类不要在同一个类中, 将@Async注解的方法,移到其它类中

循环依赖导致@Async无法初始化Bean问题 - 简书

如果B(versionSpPackageService)注入了A(distPlanService),A注入了B, 此时A中增加一个异步方法(被@Async标注的方法) 这种情况spring不能帮你解决循环依赖,此时重启项目导致报错:前因后果,需要去分析源码,这里我用别人总结的话简单说一下

        1.context.getBean(A)开始创建A,A实例化完成后给A的依赖属性b开始赋值
        2.context.getBean(B)开始创建B,B实例化完成后给B的依赖属性a开始赋值
        3.重点:此时因为A支持循环依赖,所以会执行A的getEarlyBeanReference方法得到它的早期引用。而执行getEarlyBeanReference()的时候因为@Async根本还没执行,所以最终返回的仍旧是原始对象的地址
        4.B完成初始化、完成属性的赋值,此时属性field持有的是Bean A原始类型的引用
        5.完成了A的属性的赋值(此时已持有B的实例的引用),继续执行初始化方法initializeBean(...),在此处会解析@Aysnc注解,从而生成一个代理对象,所以最终exposedObject是一个代理对象(而非原始对象)最终加入到容器里
        6.尴尬场面出现了:B引用的属性A是个原始对象,而此处准备return的实例A竟然是个代理对象,也就是说B引用的并非是最终对象(不是最终放进容器里的对象)
        7.执行自检程序:由于allowRawInjectionDespiteWrapping默认值是false,表示不允许上面不一致的情况发生,最终就抛错了。

我的解决方法:

(1)重新建class,把@Async的方法放在新的类中,从根本上消除循环依赖  不要让 @Async 的 Bean 参与循环依赖

JAVA:@Async失效(测试@Async是否生效)

JAVA:@Async失效(测试@Async是否生效)_我的麦的博客-CSDN博客

// 并行流使用的并发数是 CPU 核心数,不能局部更改。全局更改影响较大,斟酌
 streamList.parallelStream().forEach(consumer);

@Async 多线程 使用注意点_第1张图片

你可能感兴趣的:(java)