Reputation: 4696
I am testing out @Async
in a spring boot 2, and i followed some online tutorial
My Config Class:
@Configuration
@EnableAsync
public class AsyncConfig {
@Bean
public Executor asyncExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(5);
executor.setMaxPoolSize(5);
executor.setQueueCapacity(500);
executor.setThreadNamePrefix("Async Process-");
executor.initialize();
return executor;
}
}
Snippet of My Controller:
@GetMapping("/test/async")
public void testAsync() {
System.err.println("Thread in controller: " + Thread.currentThread().getName());
TestAsyncClazz clazz = new TestAsyncClazz();
clazz.testAsyncMethod();
}
My TestAsyncClass
:
public class TestAsyncClazz {
@Async
public void testAsyncMethod(){
System.err.println("Running async: "+ Thread.currentThread().getName());
}
}
When i check the print line, it shows that both of my method running on the same thread, and it didn't use the threadNamePrefix Async Process-
:
Thread in controller: http-nio-8080-exec-2
Running async: http-nio-8080-exec-2
What i did wrong? Did i misunderstand something?
Upvotes: 0
Views: 2947
Reputation: 206776
This happens because you are calling the async method on a class that you instantiate yourself using new
:
TestAsyncClazz clazz = new TestAsyncClazz();
clazz.testAsyncMethod();
If you do it this way, Spring does not have a chance to decorate the instance with the necessary proxy class that provides the actual functionality to run the method asynchronously.
This will only work the way you expect on Spring beans - in other words, do not instantiate TestAsyncClazz
yourself; define a Spring bean instance of the class, autowire that bean into your controller and then call the method on the bean.
Example:
@Configuration
@EnableAsync
public class AsyncConfig {
@Bean
public Executor asyncExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(5);
executor.setMaxPoolSize(5);
executor.setQueueCapacity(500);
executor.setThreadNamePrefix("Async Process-");
executor.initialize();
return executor;
}
// Define a Spring bean of type TestAsyncClazz
@Bean
public TestAsyncClazz testAsyncClazz() {
return new TestAsyncClazz();
}
}
@Controller
public class MyController {
// Inject the bean here
@Autowired
private TestAsyncClazz testAsyncClass;
@GetMapping("/test/async")
public void testAsync() {
System.err.println("Thread in controller: " +
Thread.currentThread().getName());
// Use the bean instead of instantiating the class yourself
testAsyncClass.testAsyncMethod();
}
}
Upvotes: 5