2

Hi I'm trying out Springs asynchronous executors and found you could use @Async. I would like to know if there is a possibility to use @Async within @Async, requirement being the need to delegate task to @Async method called within the first @Async method.

Eg : There are 100 files in a directory and need to create jobs processing 20 files in 5 threads.

StO
  • 147
  • 1
  • 12

1 Answers1

7

If the two async methods are defined in two different classes, then you will be able to call the second async method from the first one. But, if they both are in the same class, the execution of the second method will happen inline in the thread processing the first method itself. Check out this answer for more details and some workarounds for the same.

For your specific case, you can define two thread pool executors, one for the first async method and another one for the second async method. The @Async annotation has a value parameter to which you can pass the thread pool executor that should be used.

Below is an example of using two executors.

@SpringBootApplication
@EnableAspectJAutoProxy
@EnableAsync
public class MultipleExecutorsExample {

    @Bean
    public ThreadPoolTaskExecutor executor1() {
        ThreadPoolTaskExecutor threadPoolTaskExecutor = new ThreadPoolTaskExecutor();
        threadPoolTaskExecutor.setCorePoolSize(10);
        threadPoolTaskExecutor.setMaxPoolSize(10);
        threadPoolTaskExecutor.initialize();
        return threadPoolTaskExecutor;
    }

    @Bean
    public ThreadPoolTaskExecutor executor2() {
        ThreadPoolTaskExecutor threadPoolTaskExecutor = new ThreadPoolTaskExecutor();
        threadPoolTaskExecutor.setCorePoolSize(5);
        threadPoolTaskExecutor.setMaxPoolSize(5);
        threadPoolTaskExecutor.initialize();
        return threadPoolTaskExecutor;
    }

    public static void main(String[] args) throws BeansException, InterruptedException {
        ConfigurableApplicationContext context = new SpringApplicationBuilder(MultipleExecutorsExample.class)
                .web(WebApplicationType.NONE).build().run(args);
        context.getBean(Service1.class).execute();
    }

}

Service1 with the first async method

@Component
@Slf4j
public class Service1 {

    @Autowired
    private Service2 service2;

    @Async("executor1")
    public void execute() throws InterruptedException {
        log.info("Sleeping for 5 seconds");
        for (int i = 1; i <= 10; i++) {
            service2.execute();
        }
    }

}

Service2 with the second async method

@Component
@Slf4j
public class Service2 {

    @Async("executor2")
    public void execute() throws InterruptedException {
        log.info("Sleeping for 1 seconds");
        Thread.sleep(1000);
    }

}

The output from the program show that different executors are being used for the two async tasks.

018-05-30 18:44:27.557  INFO 19839 --- [  restartedMain] c.e.demo.tp.MultipleExecutorsExample     : Started MultipleExecutorsExample in 1.926 seconds (JVM running for 2.407)
2018-05-30 18:44:27.567  INFO 19839 --- [    executor1-1] com.example.demo.tp.Service1             : Sleeping for 5 seconds
2018-05-30 18:44:27.570  INFO 19839 --- [    executor2-1] com.example.demo.tp.Service2             : Sleeping for 1 seconds
2018-05-30 18:44:27.570  INFO 19839 --- [    executor2-2] com.example.demo.tp.Service2             : Sleeping for 1 seconds
2018-05-30 18:44:27.570  INFO 19839 --- [    executor2-5] com.example.demo.tp.Service2             : Sleeping for 1 seconds
Ranjith
  • 1,623
  • 3
  • 21
  • 34
  • Ranjith thank you for the answer. Can't we use one thread pool? why have you configured two? – StO May 30 '18 at 16:17
  • 1
    @StO Yes, you can use the same thread pool for both the async tasks. Somehow, I assumed that you wanted two different thread pools for the two async tasks. There are some cases where we use use multiple thread pools (Ex: If you have multiple asyc tasks like processing files, sending emails, etc and you want a single task to use up all the threads in a pool, you can configure a different pool per task). For your use case, I think a single thread pool should be sufficient. – Ranjith May 30 '18 at 16:57
  • Thank you Ranjith that was helpful – StO May 31 '18 at 04:42