Multiple Custom Thread pools to spring Async flow


In the previous post-https://onecompiler.com/posts/3ur37h9g4, we learned how to pass custom thread pool to spring async flow.

Introduction

Now we are going to learn about how to pass a multiple custom thread pools for each async flow of execution.

Enable Async behaviour using spring annotation

  1. Add '@EnableAsync' annotation to spring boot application.
  2. Add '@Async' to any spring bean method. (Other than spring bean it won't work)
  3. Create a custom thread pools and register that bean to spring container by using '@Bean' with some names
  4. Call that method, it won't block the current thread.

SpringBoot Main app - Add '@EnableAsync' on top of the class and '@Bean' on top of thread pool method

package com.oc.app;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.core.task.TaskExecutor;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

@SpringBootApplication
@EnableAsync
public class RabitMqApplication {

    public static void main(String[] args) {
        ConfigurableApplicationContext context = SpringApplication.run(RabitMqApplication.class, args);
        TestService testService = context.getBean(TestService.class);
        System.out.println("Started Main Thread");
        testService.test1();
        testService.test2();
        testService.test1();
        testService.test2();
        System.out.println("Ended Main Thread");
    }

    @Bean(name="my-pool-executor1")
    public TaskExecutor threadPoolTaskExecutor1() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(4);
        executor.setMaxPoolSize(4);
        executor.setThreadNamePrefix("pool-one");
        executor.initialize();
        return executor;
    }
    
    @Bean(name="my-pool-executor2")
    public TaskExecutor threadPoolTaskExecutor2() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(4);
        executor.setMaxPoolSize(4);
        executor.setThreadNamePrefix("pool-two");
        executor.initialize();
        return executor;
    }

}

Test Service - Add '@Asyn' on top of the method with a thread pool name

package com.oc.app;

import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;


@Component
public class TestService {

    @Async(value="my-pool-executor1")
    public void test1() {
        System.out.println("Entered test1() By Thread - " + Thread.currentThread().getName());
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("Ended test1() By Thread - " + Thread.currentThread().getName());
    }
    
    @Async(value="my-pool-executor2")
    public void test2() {
        System.out.println("Entered test2() By Thread - " + Thread.currentThread().getName());
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("Ended test2() By Thread - " + Thread.currentThread().getName());
    }
}


Output :

Started Main Thread
Ended Main Thread
Entered test2() By Thread - pool-two1
Entered test1() By Thread - pool-one2
Entered test1() By Thread - pool-one1
Entered test2() By Thread - pool-two2
Ended test2() By Thread - pool-two2
Ended test2() By Thread - pool-two1
Ended test1() By Thread - pool-one1
Ended test1() By Thread - pool-one2
  • Note: Above response will take just 5+ secs because of asynchronous execution.