hades
hades

Reputation: 4696

Springboot Async method run in same thread

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

Answers (1)

Jesper
Jesper

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

Related Questions