Spring SimpleAsyncTaskExecutor 和 ThreadPoolTaskExecutor 带有 @Async 注释
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/13401558/
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 SimpleAsyncTaskExecutor and ThreadPoolTaskExecutor with @Async annotation
提问by CAL5101
I have the following configutation:
我有以下配置:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:task="http://www.springframework.org/schema/task"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-3.0.xsd">
<context:component-scan base-package="com.abc" />
<task:annotation-driven executor="executor"/>
<task:executor id="executor" pool-size="2"/>
</beans>
Then the following class
然后下面的课
public class SomeClassImpl implements SomeClass {
@Async
@Override // overridden from the interface
public void doSomething(){
System.out.println("doing something async");
}
}
A test:
一个测试:
@ContextConfiguration("classpath:test-config.xml") // with the xml config above
@RunWith(value = SpringJUnit4ClassRunner.class)
public class SomeClassTest {
@Autowired
private SomeClass someClass;
@Test
public void testSomething() throws Exception {
System.out.println("Calling doSomething");
someClass.doSomething();
Thread.sleep(5000);
}
}
When I ran the test, everything worked as expected. But then I attached the debugger to step through what is actually happening when someClass.doSomething() is called and i noticed the following:
当我运行测试时,一切都按预期进行。但是后来我附加了调试器来逐步完成调用 someClass.doSomething() 时实际发生的事情,我注意到以下内容:


Why is it that 4 threads are being created by a SimpleAsyncTaskExecutor? I know that if I remove the executor property from the task:annotation-driven xml element, the AsyncExecutionInterceptor will use the SimpleAsyncTaskExecutor. But since I have declared a task executor and referenced it from the annotation-driven element, why is a SimpleAsyncTaskExecutor being created?
为什么 SimpleAsyncTaskExecutor 创建了 4 个线程?我知道如果我从 task:annotation-driven xml 元素中删除 executor 属性,AsyncExecutionInterceptor 将使用 SimpleAsyncTaskExecutor。但是既然我已经声明了一个任务执行器并从注释驱动的元素中引用了它,为什么要创建一个 SimpleAsyncTaskExecutor 呢?
回答by pmhargis
First of all, if using Java 5 and above (required for Java Futures, etc), the default TaskExecutor implementation should be the ThreadPoolTaskExecutor, which matches your debug trace output. This is the thread manager actually executing your test code.
首先,如果使用 Java 5 及更高版本(Java Futures 等需要),默认的 TaskExecutor 实现应该是 ThreadPoolTaskExecutor,它与您的调试跟踪输出匹配。这是实际执行测试代码的线程管理器。
The SimpleAsyncTaskExecutor is likely being launched as part of the Spring task executor framework, possibly from another annotation in your test context file. The Spring container may be launching four instances of the SimpleAsyncTaskExecutor class. According to Spring documentation, this version of the TaskExecutor never re-uses threads to satisfy new requests (it will start a new thread):
SimpleAsyncTaskExecutor 可能作为 Spring 任务执行器框架的一部分启动,可能来自测试上下文文件中的另一个注释。Spring 容器可能会启动 SimpleAsyncTaskExecutor 类的四个实例。根据 Spring 文档,此版本的 TaskExecutor 从不重用线程来满足新请求(它将启动一个新线程):
SimpleAsyncTaskExecutor
简单异步任务执行器
This implementation does not reuse any threads, rather it starts up a new thread for each invocation. However, it does support a concurrency limit which will block any invocations that are over the limit until a slot has been freed up. If you're looking for true pooling, keep scrolling further down the page.
此实现不重用任何线程,而是为每次调用启动一个新线程。但是,它确实支持并发限制,该限制将阻止任何超出限制的调用,直到插槽被释放为止。如果您正在寻找真正的池化,请继续向下滚动页面。
参考:http: //docs.spring.io/spring/docs/3.1.x/spring-framework-reference/html/scheduling.html#scheduling-task-executor
Therefore, this could be the result of interactions between the test context and the Spring container.
因此,这可能是测试上下文和 Spring 容器之间交互的结果。
I believe you have a single thread running your test code in this scenario, which is what you expect, based on a single request. Spring TaskExecutor implementations leverage a helper class called ConcurrencyThrottleSupport which is supposed to throttle (limit) the number of concurrent threads in execution. In your case, this should be 2, as indicated by the pool-size property. However, to run this one test, it should never need to allocate an additional thread, and the trace output agrees with this.
我相信在这种情况下您有一个线程运行您的测试代码,这正是您期望的,基于单个请求。Spring TaskExecutor 实现利用了一个名为 ConcurrencyThrottleSupport 的辅助类,它应该节流(限制)执行中的并发线程数。在您的情况下,这应该是 2,如 pool-size 属性所示。但是,要运行这个测试,它永远不需要分配额外的线程,并且跟踪输出也同意这一点。

