从另一个异步方法调用的 Spring 异步方法 [英] Spring async method called from another async method

查看:46
本文介绍了从另一个异步方法调用的 Spring 异步方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm using Spring 4 and I've noticed an odd behaviour... if I'm calling an async method multiple times from a normal instance method then they are all called in different threads and finish at random times. But if I call multiple times an async method from another async method then they finish in order. I have something like this:

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

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

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

I'm using the default async executor. Should I use a different one? However this executor do not reuse any threads and starts another one every time so it should be fine... Can it be just a coincidence? But I've tried like more than 10 times and if I revert back to non-async for the first method then they finish randomly

推荐答案

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

What you are describing is a classic pitfall of Spring AOP.

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

In short, for Spring to be able to provide the async behavior it needs to create a proxy for your class at runtime. The proxy then does whatever it needs to do before and/or after calling your code. But in your case, the proxy mechanism is not being applied for the second method.

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

When a bean of your class is injected via Spring into some other component, Spring really injects the proxy instead. Therefor the relevant method of the proxy is called. However, when you are calling a method from inside the class, the limitations of Spring AOP mean the proxy never comes into play, but instead the regular method is called - with no extra features.

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

That is why asyncMethod is always executing on the same thread as the other method in the same class that called it.

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

Check out this excellent blog post as well as this part of Spring documentation.

有一些方法可以解决这个问题(查看这个) 不需要你重构你的代码,但如果你无论如何都希望异步处理这两种方法,最简单的方法就是将第二种方法重构到另一个类中.

There are some ways around the problem (check out this) that don't require you to refactor your code, but if you want async to work on both methods no matter what, the simplest thing to do is refactor the second method into another class.

这篇关于从另一个异步方法调用的 Spring 异步方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆