gpt4 book ai didi

带 @Async 注解的 Spring SimpleAsyncTaskExecutor 和 ThreadPoolTask​​Executor

转载 作者:行者123 更新时间:2023-12-02 04:15:19 24 4
gpt4 key购买 nike

我有以下配置:

<?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>

然后是下面的类

public class SomeClassImpl implements SomeClass {

@Async
@Override // overridden from the interface
public void doSomething(){
System.out.println("doing something async");
}
}

测试:

@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);
}
}

当我运行测试时,一切都按预期进行。但后来我附加了调试器来逐步了解调用 someClass.doSomething() 时实际发生的情况,并且我注意到以下内容:

enter image description here

为什么 SimpleAsyncTaskExecutor 创建了 4 个线程?我知道,如果我从任务:注释驱动的 xml 元素中删除 executor 属性,AsyncExecutionInterceptor 将使用 SimpleAsyncTaskExecutor。但是既然我已经声明了一个任务执行器并从注释驱动元素引用了它,为什么会创建一个 SimpleAsyncTaskExecutor 呢?

最佳答案

首先,如果使用 Java 5 及更高版本(Java Futures 等所需),默认的 TaskExecutor 实现应该是 ThreadPoolTask​​Executor,它与您的调试跟踪输出相匹配。这是实际执行测试代码的线程管理器。

SimpleAsyncTaskExecutor 可能作为 Spring 任务执行器框架的一部分启动,可能来自测试上下文文件中的另一个注释。 Spring 容器可能正在启动 SimpleAsyncTaskExecutor 类的四个实例。根据 Spring 文档,此版本的 TaskExecutor 从不重复使用线程来满足新请求(它将启动一个新线程):

简单AsyncTaskExecutor

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

因此,这可能是测试上下文和 Spring 容器之间交互的结果。

我相信在这种情况下您有一个线程运行您的测试代码,这正是您所期望的,基于单个请求。 Spring TaskExecutor 实现利用一个名为 ConcurrencyThrottleSupport 的帮助器类,该类应该限制(限制)执行中的并发线程数。在您的情况下,这应该是 2,如 pool-size 属性所示。然而,要运行这个测试,它永远不需要分配额外的线程,并且跟踪输出与此一致。

关于带 @Async 注解的 Spring SimpleAsyncTaskExecutor 和 ThreadPoolTask​​Executor,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13401558/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com