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

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

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

@Async
public void asyncMethod() {
   ... something here
}

我正在使用默认的异步执行器。我应该使用其他的吗?但是,此执行器不会重用任何线程,并且每次都会启动另一个线程,因此应该没问题...这可能只是一个巧合吗?但是我已经尝试了10多次,如果我恢复到第一种方法的非异步,那么它们会随机完成


答案 1

你所描述的是Spring AOP的一个经典陷阱。

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

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

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

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

有一些方法可以解决这个问题(看看这个),不需要你重构你的代码,但是如果你想让异步无论如何都在这两个方法上工作,最简单的办法就是将第二个方法重构到另一个类中。


答案 2

推荐