java Spring 3.x - 任务执行器不会同时调用@Async 方法
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/17735455/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Spring 3.x - @Async methods not called concurrently by task executor
提问by tarares
I'm trying to implement concurrent method invocation in my Service class.
我正在尝试在我的 Service 类中实现并发方法调用。
I've some methods annotated as @Async in my service class and I'm trying to call all these methods concurrently. But the methods are executing sequentially.
我在我的服务类中将一些方法注释为 @Async,并且我正在尝试同时调用所有这些方法。但是这些方法是按顺序执行的。
This is my service class(dummy):
这是我的服务类(虚拟):
@Service public class TestService {
public SomeDataType getSOmeDataType() {
try {
List<DataType> a = retrieveDataA().get();
List<DataType> b = retrieveDataB().get();
List<DataType> c = retrieveDataC().get();
List<DataType> d = retrieveDataD().get();
List<DataType> e = retrieveDataE().get();
}
catch (InterruptedException e) {
e.printStackTrace();
}
catch (ExecutionException e) {
e.printStackTrace();
}
return referralDetailsReferenceData;
}
@Async
private Future<List<DataType>> retrieveDataA() {
//method logic
}
@Async
private Future<List<DataType>> retrieveDataB() {
//method logic
}
@Async
private Future<List<DataType>> retrieveDataC() {
//method logic
}
@Async
private Future<List<DataType>> retrieveDataD() {
//method logic
}
@Async
private Future<List<DataType>> retrieveDataE() {
//method logic
}
This is my spring config:
这是我的弹簧配置:
<bean id="executorService" class="java.util.concurrent.Executors" factory-method="newFixedThreadPool">
<constructor-arg value="10" />
</bean>
<task:executor id="threadPoolTaskExecutor" pool-size="10" />
<task:annotation-driven executor="executorService" />
When "getSomeDataType" is executed the methods are invoked sequentially.
当“getSomeDataType”被执行时,这些方法被顺序调用。
I'm new to @Async and concurrent execution in Spring, so I'm sure I'm doing something silly. But I'm not able to figure it out.
我是 Spring 中 @Async 和并发执行的新手,所以我确定我在做一些愚蠢的事情。但我无法弄清楚。
Any suggestions is highly appreciated.
任何建议都非常感谢。
回答by sehrope
The issue is that you're calling the methods internally so they're not proxied. For the @Async
to work you need to retrieve the object from your application context and invoke the methods on the retrieved copy. Invoking it internally will not work.
问题是您在内部调用这些方法,因此它们不会被代理。为了@Async
工作,您需要从应用程序上下文中检索对象并调用检索到的副本上的方法。在内部调用它是行不通的。
The same thing happens if you try to invoke internal @Transactional
methods. See the Note:section at the end of the Spring docsexplaining @Transactional
for details.
如果您尝试调用内部@Transactional
方法,也会发生同样的事情。见注:部分在结束春节文档说明@Transactional
的详细信息。
Additionally, the way you're immediately calling .get()
on the Future
return values is incorrect. If you want them to happen in parallel you should submit allthe tasks then retrieve each one via .get()
.
此外,你马上打电话的方式.get()
对Future
返回值不正确。如果您希望它们并行发生,您应该提交所有任务,然后通过.get()
.
The usual approach is to handle the proxying issue is to create a separate service class that gets TestService
injected into it and calls the @Async
service methods directly:
处理代理问题的常用方法是创建一个单独的服务类,将其TestService
注入其中并@Async
直接调用服务方法:
@Service public class TestServiceHelper {
@Autowired
TestService testService;
public SomeDataType getSOmeDataType() {
try {
// Invoke all of them async:
Future<List<DataType>> a = testService.retrieveDataA();
Future<List<DataType>> b = testService.retrieveDataA();
Future<List<DataType>> c = testService.retrieveDataA();
Future<List<DataType>> d = testService.retrieveDataA();
Future<List<DataType>> e = testService.retrieveDataA();
// Wait for each sequentially:
List<DataType> aList = a.get();
List<DataType> bList = b.get();
List<DataType> cList = c.get();
List<DataType> dList = d.get();
List<DataType> eList = e.get();
// do work with lists here ...
}
catch (InterruptedException e) {
e.printStackTrace();
}
catch (ExecutionException e) {
e.printStackTrace();
}
return referralDetailsReferenceData;
}
}
An alternative to the above separate service bean (quite hackish/not recommended!) is to inject the object into itself and use the injected copy to invoke the @Async
methods.
上面单独的服务 bean 的替代方案(非常hackish/不推荐!)是将对象注入自身并使用注入的副本来调用@Async
方法。