从另一个异步方法调用的Spring异步方法

spa*_*uny 20 java spring multithreading asynchronous spring-4

我正在使用Spring 4,我注意到一个奇怪的行为......如果我从普通实例方法多次调用异步方法,那么它们都会在不同的线程中调用并随机完成.但是,如果我从另一个异步方法多次调用异步方法,那么它们按顺序完成.我有这样的事情:

@Async
public void nonAsyncMethod() {
  for (int i = 0; i < 30; i++) {
     asyncMethod();
  }
}

@Async
public void asyncMethod() {
   ... something here
}
Run Code Online (Sandbox Code Playgroud)

我正在使用默认的异步执行程序.我应该使用另一个吗?然而,这个执行器不会重复使用任何线程并且每次都启动另一个线程所以它应该没问题......它只是巧合吗?但我尝试过10次以上,如果我恢复到第一种方法的非异步,那么他们会随机完成

geo*_*and 50

你所描述的是Spring AOP的经典陷阱.

简而言之,为了能够提供异步行为,它需要在运行时为您的类创建代理.然后代理在调用代码之前和/或之后执行它需要做的任何事情.但在您的情况下,代理机制未应用于第二种方法.

当你的类的bean通过Spring注入到其他组件中时,Spring确实会注入代理.因此,调用代理的相关方法.但是,当您从类中调用方法时,Spring AOP的限制意味着代理永远不会发挥作用,而是调用常规方法 - 没有额外的功能.

这就是为什么asyncMethod总是在与调用它的同一个类中的另一个方法相同的线程上执行的原因.

查看这篇优秀的博客文章以及Spring文档的这一部分.

有一些解决问题的方法(请查看这个)不需要你重构你的代码,但是如果你想让异步同时处理两种方法,最简单的方法就是将第二种方法重构为另一种类.