Please Look at this below piece of code:
@Autowired
private ThreadPoolTaskExecutor executor;
@PostConstruct
public void setupTaskExecutor() {
this.executor.setCorePoolSize(getExecutorCorePoolSize());
this.executor.setMaxPoolSize(getExecutorMaxPoolSize());
this.executor.setQueueCapacity(getExecutorMaxQueueCapacity());
}
public ZoneDetail getZoneDetails(ConfigRequest configRequest) {
LOGGER.debug("QueueSize = {}", executor.getThreadPoolExecutor().getQueue().size());
LOGGER.debug("PoolSize = {}", executor.getPoolSize());
Future<ZoneDetail> future = executor.submit(() -> {
return getPrimaryProvider(context).getZoneDetails(context,
configRequest);
});
try {
ZoneDetail zoneDetail = future.get(getPrimaryProviderTimeout(),
TimeUnit.MILLISECONDS);
} catch (ExecutionException | TimeoutException e) {
// fetch data from secondary provider
}
}
My configured values are
core-pool-size=4
max-pool-size=16
max-queue-capacity=5
I run a PT using SoapUI with following parameters,
Threads: 20 Strategy: Simple Test Delay: 0 Limit: 5 seconds
i.e. I am hitting 20 Threads at a time for 5 seconds.
In the console, I see QueueSize = 15 i.e. my queue size exceeds the configured max queue capacity 5. And PoolSize = 4 i.e. my pool size never exceeds core pool size since extra threads are going into queue.
Note: I am hitting a REST API that calls getZoneDetails() method
How is it happening? What am I doing wrong ?
I don't think your setup is correct. You are autowiring ThreadPoolTaskExecutor
and it means it would have been already initialised the ThreadPoolExecutor
with QueueCapacity
of Integer.MAX_VALUE
and created a queue with that capacity. So whatever you do in setupTaskExecutor()
is not going to take effect.
Instead do the following in one go
@Bean(name = "myThreadPoolTaskExecutor")
public Executor threadPoolTaskExecutor() {
ThreadPoolTaskExecutor threadPoolTaskExecutor =
new ThreadPoolTaskExecutor();
threadPoolTaskExecutor.setCorePoolSize(getExecutorCorePoolSize());
threadPoolTaskExecutor.setMaxPoolSize(getExecutorMaxPoolSize());
threadPoolTaskExecutor.setQueueCapacity(getExecutorMaxQueueCapacity());
threadPoolTaskExecutor.initialize();
return threadPoolTaskExecutor;
}
If you add LOGGER.debug("RemainingCapacity = {}", this.executor.getThreadPoolExecutor().getQueue().remainingCapacity())
as the last line of setupTaskExecutor()
, it should confirm this answer
And then use it
@Autowired
@Qualifier("myThreadPoolTaskExecutor")
public ThreadPoolTaskExecutor executor;