0

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?

1 Answer 1

5

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(); } } 
Sign up to request clarification or add additional context in comments.

2 Comments

so other than @Bean, i can actually autowired @Service, or @Repository classes too right, and the @Async will works?
Yes, @Service and @Repository classes are also Spring beans.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.