Custom thread pools help control how many tasks run at the same time. This keeps your app fast and stable.
Custom thread pool configuration in Spring Boot
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; @Configuration public class ThreadPoolConfig { @Bean(name = "customThreadPool") public ThreadPoolTaskExecutor threadPoolTaskExecutor() { ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); executor.setCorePoolSize(5); // minimum threads executor.setMaxPoolSize(10); // max threads executor.setQueueCapacity(25); // tasks waiting executor.setThreadNamePrefix("MyPool-"); executor.initialize(); return executor; } }
Use @Configuration to tell Spring this is a setup class.
@Bean creates the thread pool object for Spring to use.
executor.setCorePoolSize(3); executor.setMaxPoolSize(6); executor.setQueueCapacity(50);
executor.setThreadNamePrefix("Worker-");executor.setKeepAliveSeconds(60);This Spring Boot app creates a custom thread pool with 2 to 4 threads. It runs 5 tasks that print their thread name and task number. You see how threads from the pool handle tasks concurrently.
import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.annotation.Bean; import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import java.util.concurrent.Executor; @SpringBootApplication public class ThreadPoolApp { public static void main(String[] args) { var context = SpringApplication.run(ThreadPoolApp.class, args); TaskRunner runner = context.getBean(TaskRunner.class); runner.runTasks(); } @Bean(name = "customThreadPool") public ThreadPoolTaskExecutor threadPoolTaskExecutor() { ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); executor.setCorePoolSize(2); executor.setMaxPoolSize(4); executor.setQueueCapacity(10); executor.setThreadNamePrefix("CustomPool-"); executor.initialize(); return executor; } } @Component class TaskRunner { @Autowired private Executor customThreadPool; public void runTasks() { for (int i = 1; i <= 5; i++) { int taskId = i; customThreadPool.execute(() -> { System.out.println(Thread.currentThread().getName() + " is running task " + taskId); try { Thread.sleep(500); // simulate work } catch (InterruptedException e) { Thread.currentThread().interrupt(); } }); } } }
Core pool size is the number of threads always kept alive.
Max pool size is the max threads allowed when demand is high.
Queue capacity holds tasks waiting when all threads are busy.
Custom thread pools help manage background tasks efficiently.
Set core size, max size, and queue to control thread behavior.
Use thread name prefixes to make debugging easier.
Practice
Solution
Step 1: Understand thread pools in Spring Boot
Thread pools manage how many threads run tasks concurrently, improving performance and resource use.Step 2: Identify the role of custom thread pools
Custom thread pools let you set limits on thread count and behavior for asynchronous processing.Final Answer:
To control the number of threads used for asynchronous tasks -> Option BQuick Check:
Thread pool purpose = control threads [OK]
- Confusing thread pool with database or HTTP settings
- Thinking thread pools affect logging
- Assuming thread pools are for UI rendering
Solution
Step 1: Recall Spring Boot thread pool bean creation
Spring Boot uses ThreadPoolTaskExecutor for custom thread pools, which integrates with Spring's task execution.Step 2: Analyze options
@Bean public Executor taskExecutor() { return new ThreadPoolTaskExecutor(); } correctly returns a new ThreadPoolTaskExecutor instance, which is the recommended way.Final Answer:
@Bean public Executor taskExecutor() { return new ThreadPoolTaskExecutor(); } -> Option DQuick Check:
Spring thread pool bean = ThreadPoolTaskExecutor [OK]
- Using Executors.newFixedThreadPool directly without Spring wrapper
- Trying to instantiate ThreadPoolExecutor without parameters
- Confusing scheduled thread pools with normal thread pools
@Bean
public ThreadPoolTaskExecutor taskExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(3);
executor.setMaxPoolSize(6);
executor.setQueueCapacity(10);
executor.initialize();
return executor;
}Solution
Step 1: Understand core and max pool size
Core pool size is minimum threads kept alive; max pool size is the maximum threads allowed.Step 2: Identify maxPoolSize value
The code sets maxPoolSize to 6, so the pool can grow up to 6 threads.Final Answer:
6 -> Option AQuick Check:
Max threads = maxPoolSize = 6 [OK]
- Confusing queue capacity with max threads
- Thinking corePoolSize is max threads
- Adding corePoolSize and queueCapacity incorrectly
@Bean
public ThreadPoolTaskExecutor taskExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(5);
executor.setMaxPoolSize(3);
executor.setQueueCapacity(10);
executor.initialize();
return executor;
}Solution
Step 1: Check core and max pool size relationship
Core pool size must be less than or equal to max pool size; here core is 5 but max is 3, which is invalid.Step 2: Validate other settings
Queue capacity is valid; @EnableAsync is optional but recommended; returning ThreadPoolTaskExecutor bean is correct.Final Answer:
Core pool size is greater than max pool size, which is invalid -> Option CQuick Check:
Core pool ≤ max pool required [OK]
- Setting core pool size larger than max pool size
- Assuming queue capacity is mandatory to set
- Forgetting to add @EnableAsync (not always required)
Solution
Step 1: Verify core, max pool sizes and queue capacity
Core pool size 4, max pool size 8, and queue capacity 20 match the requirement in @Bean public ThreadPoolTaskExecutor taskExecutor() { ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); executor.setCorePoolSize(4); executor.setMaxPoolSize(8); executor.setQueueCapacity(20); executor.setThreadNamePrefix("MyApp-"); executor.initialize(); return executor; }.Step 2: Check thread name prefix correctness
@Bean public ThreadPoolTaskExecutor taskExecutor() { ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); executor.setCorePoolSize(4); executor.setMaxPoolSize(8); executor.setQueueCapacity(20); executor.setThreadNamePrefix("MyApp-"); executor.initialize(); return executor; } sets thread name prefix to "MyApp-" exactly as requested.Step 3: Validate other options
@Bean public Executor taskExecutor() { return Executors.newFixedThreadPool(8); } uses fixed thread pool without prefix; @Bean public ThreadPoolTaskExecutor taskExecutor() { ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); executor.setCorePoolSize(8); executor.setMaxPoolSize(4); executor.setQueueCapacity(20); executor.setThreadNamePrefix("MyApp-"); executor.initialize(); return executor; } reverses core and max sizes (invalid); @Bean public ThreadPoolTaskExecutor taskExecutor() { ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); executor.setCorePoolSize(4); executor.setMaxPoolSize(8); executor.setQueueCapacity(20); executor.setThreadNamePrefix("App-"); executor.initialize(); return executor; } uses wrong prefix.Final Answer:
Option A code snippet correctly implements the required configuration -> Option AQuick Check:
Correct sizes and prefix = @Bean public ThreadPoolTaskExecutor taskExecutor() { ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); executor.setCorePoolSize(4); executor.setMaxPoolSize(8); executor.setQueueCapacity(20); executor.setThreadNamePrefix("MyApp-"); executor.initialize(); return executor; } [OK]
- Swapping core and max pool sizes
- Using wrong thread name prefix
- Using fixed thread pool instead of ThreadPoolTaskExecutor
Ready to prove it?
Pass the test and this pattern moves unknown
