队列大小超过 spring 引导中使用的 ThreadPoolTask​​Executor 中配置的最大队列容量

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_VALUEQueueCapacity 初始化了 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;