队列大小超过 spring 引导中使用的 ThreadPoolTaskExecutor 中配置的最大队列容量
Queue size exceeds from configured max queue capacity in ThreadPoolTaskExecutor used in spring boot
请看下面这段代码:
@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
}
}
我配置的值为
核心池大小=4
最大池大小=16
最大队列容量=5
我 运行 PT 使用具有以下参数的 SoapUI,
Threads: 20 Strategy: Simple Test Delay: 0 Limit: 5 seconds
即我一次点击 20 个线程,持续 5 秒。
在控制台中,我看到 QueueSize = 15 即我的队列大小超过配置的最大队列容量 5。并且 PoolSize = 4即我的池大小永远不会超过核心池大小,因为额外的线程正在进入队列。
注意:我正在调用调用 getZoneDetails() 方法的 REST API
这是怎么回事?我做错了什么?
我认为您的设置不正确。您正在自动装配 ThreadPoolTaskExecutor
,这意味着它已经用 Integer.MAX_VALUE
的 QueueCapacity
初始化了 ThreadPoolExecutor
并创建了具有该容量的队列。所以你在 setupTaskExecutor()
中所做的任何事情都不会生效。
而是一次完成以下操作
@Bean(name = "myThreadPoolTaskExecutor")
public Executor threadPoolTaskExecutor() {
ThreadPoolTaskExecutor threadPoolTaskExecutor =
new ThreadPoolTaskExecutor();
threadPoolTaskExecutor.setCorePoolSize(getExecutorCorePoolSize());
threadPoolTaskExecutor.setMaxPoolSize(getExecutorMaxPoolSize());
threadPoolTaskExecutor.setQueueCapacity(getExecutorMaxQueueCapacity());
threadPoolTaskExecutor.initialize();
return threadPoolTaskExecutor;
}
如果你在setupTaskExecutor()
的最后一行添加LOGGER.debug("RemainingCapacity = {}", this.executor.getThreadPoolExecutor().getQueue().remainingCapacity())
,它应该确认这个答案
然后使用
@Autowired
@Qualifier("myThreadPoolTaskExecutor")
public ThreadPoolTaskExecutor executor;
请看下面这段代码:
@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
}
}
我配置的值为
核心池大小=4
最大池大小=16
最大队列容量=5
我 运行 PT 使用具有以下参数的 SoapUI,
Threads: 20 Strategy: Simple Test Delay: 0 Limit: 5 seconds
即我一次点击 20 个线程,持续 5 秒。
在控制台中,我看到 QueueSize = 15 即我的队列大小超过配置的最大队列容量 5。并且 PoolSize = 4即我的池大小永远不会超过核心池大小,因为额外的线程正在进入队列。
注意:我正在调用调用 getZoneDetails() 方法的 REST API
这是怎么回事?我做错了什么?
我认为您的设置不正确。您正在自动装配
ThreadPoolTaskExecutor
,这意味着它已经用Integer.MAX_VALUE
的QueueCapacity
初始化了ThreadPoolExecutor
并创建了具有该容量的队列。所以你在setupTaskExecutor()
中所做的任何事情都不会生效。而是一次完成以下操作
@Bean(name = "myThreadPoolTaskExecutor")
public Executor threadPoolTaskExecutor() {
ThreadPoolTaskExecutor threadPoolTaskExecutor =
new ThreadPoolTaskExecutor();
threadPoolTaskExecutor.setCorePoolSize(getExecutorCorePoolSize());
threadPoolTaskExecutor.setMaxPoolSize(getExecutorMaxPoolSize());
threadPoolTaskExecutor.setQueueCapacity(getExecutorMaxQueueCapacity());
threadPoolTaskExecutor.initialize();
return threadPoolTaskExecutor;
}
如果你在
setupTaskExecutor()
的最后一行添加LOGGER.debug("RemainingCapacity = {}", this.executor.getThreadPoolExecutor().getQueue().remainingCapacity())
,它应该确认这个答案然后使用
@Autowired
@Qualifier("myThreadPoolTaskExecutor")
public ThreadPoolTaskExecutor executor;