diff --git a/spring-context/src/main/java/org/springframework/scheduling/concurrent/ThreadPoolTaskExecutor.java b/spring-context/src/main/java/org/springframework/scheduling/concurrent/ThreadPoolTaskExecutor.java index 624191e23482..1fb2708bcca2 100644 --- a/spring-context/src/main/java/org/springframework/scheduling/concurrent/ThreadPoolTaskExecutor.java +++ b/spring-context/src/main/java/org/springframework/scheduling/concurrent/ThreadPoolTaskExecutor.java @@ -72,6 +72,8 @@ * {@link org.springframework.scheduling.concurrent.ConcurrentTaskExecutor} adapter. * * @author Juergen Hoeller + * @author Rémy Guihard + * @author Sam Brannen * @since 2.0 * @see org.springframework.core.task.TaskExecutor * @see java.util.concurrent.ThreadPoolExecutor @@ -155,7 +157,7 @@ public int getMaxPoolSize() { /** * Set the ThreadPoolExecutor's keep-alive seconds. - * Default is 60. + *

Default is 60. *

This setting can be modified at runtime, for example through JMX. */ public void setKeepAliveSeconds(int keepAliveSeconds) { @@ -178,7 +180,7 @@ public int getKeepAliveSeconds() { /** * Set the capacity for the ThreadPoolExecutor's BlockingQueue. - * Default is {@code Integer.MAX_VALUE}. + *

Default is {@code Integer.MAX_VALUE}. *

Any positive value will lead to a LinkedBlockingQueue instance; * any other value will lead to a SynchronousQueue instance. * @see java.util.concurrent.LinkedBlockingQueue @@ -188,6 +190,15 @@ public void setQueueCapacity(int queueCapacity) { this.queueCapacity = queueCapacity; } + /** + * Return the capacity for the ThreadPoolExecutor's BlockingQueue. + * @since 5.3.21 + * @see #setQueueCapacity(int) + */ + public int getQueueCapacity() { + return this.queueCapacity; + } + /** * Specify whether to allow core threads to time out. This enables dynamic * growing and shrinking even in combination with a non-zero queue (since @@ -315,19 +326,18 @@ public int getPoolSize() { } return this.threadPoolExecutor.getPoolSize(); } - - /** - * Return the current number of threads waiting in the queue - */ - public int getCurrentQueueSize() { - return this.getThreadPoolExecutor().getQueue().size(); - } /** - * Return the maximum capacity of the queue - */ - public int getQueueCapacity() { - return this.queueCapacity; + * Return the current queue size. + * @since 5.3.21 + * @see java.util.concurrent.ThreadPoolExecutor#getQueue() + */ + public int getQueueSize() { + if (this.threadPoolExecutor == null) { + // Not initialized yet: assume no queued tasks. + return 0; + } + return this.threadPoolExecutor.getQueue().size(); } /** diff --git a/spring-context/src/test/java/org/springframework/scheduling/concurrent/ThreadPoolTaskExecutorTests.java b/spring-context/src/test/java/org/springframework/scheduling/concurrent/ThreadPoolTaskExecutorTests.java index afc629b882ae..0723a27abf79 100644 --- a/spring-context/src/test/java/org/springframework/scheduling/concurrent/ThreadPoolTaskExecutorTests.java +++ b/spring-context/src/test/java/org/springframework/scheduling/concurrent/ThreadPoolTaskExecutorTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2021 the original author or authors. + * Copyright 2002-2022 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,6 +16,9 @@ package org.springframework.scheduling.concurrent; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.SynchronousQueue; import java.util.concurrent.TimeUnit; import org.junit.jupiter.api.Test; @@ -23,10 +26,15 @@ import org.springframework.core.task.AsyncListenableTaskExecutor; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatIllegalStateException; import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.assertj.core.api.InstanceOfAssertFactories.type; /** + * Unit tests for {@link ThreadPoolTaskExecutor}. + * * @author Juergen Hoeller + * @author Sam Brannen * @since 5.0.5 */ class ThreadPoolTaskExecutorTests extends AbstractSchedulingTaskExecutorTests { @@ -50,8 +58,8 @@ void modifyCorePoolSizeWhileRunning() { executor.setCorePoolSize(0); - assertThat(executor.getCorePoolSize()).isEqualTo(0); - assertThat(executor.getThreadPoolExecutor().getCorePoolSize()).isEqualTo(0); + assertThat(executor.getCorePoolSize()).isZero(); + assertThat(executor.getThreadPoolExecutor().getCorePoolSize()).isZero(); } @Test @@ -112,4 +120,37 @@ void modifyKeepAliveSecondsWithInvalidValueWhileRunning() { assertThat(executor.getThreadPoolExecutor().getKeepAliveTime(TimeUnit.SECONDS)).isEqualTo(60); } + @Test + void queueCapacityDefault() { + assertThat(executor.getQueueCapacity()).isEqualTo(Integer.MAX_VALUE); + assertThat(executor.getThreadPoolExecutor().getQueue()) + .asInstanceOf(type(LinkedBlockingQueue.class)) + .extracting(BlockingQueue::remainingCapacity).isEqualTo(Integer.MAX_VALUE); + } + + @Test + void queueCapacityZero() { + executor.setQueueCapacity(0); + executor.afterPropertiesSet(); + + assertThat(executor.getQueueCapacity()).isZero(); + assertThat(executor.getThreadPoolExecutor().getQueue()) + .asInstanceOf(type(SynchronousQueue.class)) + .extracting(BlockingQueue::remainingCapacity).isEqualTo(0); + } + + @Test + void queueSize() { + ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); + + assertThatIllegalStateException().isThrownBy(executor::getThreadPoolExecutor); + assertThat(executor.getQueueSize()).isZero(); + + executor.afterPropertiesSet(); + + assertThat(executor.getThreadPoolExecutor()).isNotNull(); + assertThat(executor.getThreadPoolExecutor().getQueue()).isEmpty(); + assertThat(executor.getQueueSize()).isZero(); + } + }