Spring SimpleAsyncTaskExecutor and ThreadPoolTaskExecutor with @Async annotation

I have the following configuration:

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

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

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 hooked up the debugger to accomplish what actually happens when someClass.doSomething () is called, and I noticed the following:

enter image description here

Why are there 4 threads created by SimpleAsyncTaskExecutor? I know that if I remove the executor property from the task: the xml element associated with the annotation, AsyncExecutionInterceptor will use the SimpleAsyncTaskExecutor. But since I declared the task executor and referenced it from an annotation-dependent element, why is SimpleAsyncTaskExecutor created?

+4
source share
1 answer

First of all, if you use Java 5 and higher (required for Java Futures, etc.), then the default TaskExecutor should be ThreadPoolTaskExecutor, which corresponds to the output of the debug trace. This is a thread manager that actually runs your test code.

Simple AsyncTaskExecutor most likely starts as part of the Spring task runtime, possibly from a different annotation in your test context file. A Spring container can run four instances of the SimpleAsyncTaskExecutor class. According to Spring documentation, this version of TaskExecutor never repeats using threads to satisfy new requests (it will start a new thread):

SimpleAsyncTaskExecutor

This implementation does not use many threads, but launches a new thread for each call. However, it maintains a concurrency limit that blocks any that exceed the limit until the slot is freed. If you are looking for true unification, keep scrolling down the page.

Link: http://docs.spring.io/spring/docs/3.1.x/spring-framework-reference/html/scheduling.html#scheduling-task-executor

Therefore, this may be the result of the interaction between the test context and the Spring container.

I believe that in this scenario there is one thread that runs your test code, and this is what you expect based on a single request. Spring TaskExecutor implementations use the ConcurrencyThrottleSupport helper class, which must throttle (limit) the number of concurrent threads on execution. In your case, it should be 2, as indicated by the pool size property. However, to run this test, you never need to allocate an extra thread, and the trace output is consistent with this.

+6
source

Source: https://habr.com/ru/post/1446274/


All Articles