From 597c58f43d07361bad9dceb4ae1b5859b8fa2be6 Mon Sep 17 00:00:00 2001 From: Yanming Zhou Date: Fri, 11 Apr 2025 08:56:30 +0800 Subject: [PATCH 1/2] Add support for SimpleTaskExecutor#reject-tasks-when-limit-reached See gh-45155 Signed-off-by: Yanming Zhou --- .../task/TaskExecutionProperties.java | 13 +++++++ .../task/TaskExecutorConfigurations.java | 1 + .../TaskExecutionAutoConfigurationTests.java | 2 + .../task/SimpleAsyncTaskExecutorBuilder.java | 39 ++++++++++++++----- .../SimpleAsyncTaskExecutorBuilderTests.java | 7 ++++ 5 files changed, 52 insertions(+), 10 deletions(-) diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/task/TaskExecutionProperties.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/task/TaskExecutionProperties.java index 759d336bc23..fb5ed887d24 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/task/TaskExecutionProperties.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/task/TaskExecutionProperties.java @@ -83,6 +83,11 @@ public class TaskExecutionProperties { */ private Integer concurrencyLimit; + /** + * Specify whether to reject tasks when the concurrency limit has been reached. + */ + private boolean rejectTasksWhenLimitReached; + public Integer getConcurrencyLimit() { return this.concurrencyLimit; } @@ -91,6 +96,14 @@ public class TaskExecutionProperties { this.concurrencyLimit = concurrencyLimit; } + public boolean isRejectTasksWhenLimitReached() { + return this.rejectTasksWhenLimitReached; + } + + public void setRejectTasksWhenLimitReached(boolean rejectTasksWhenLimitReached) { + this.rejectTasksWhenLimitReached = rejectTasksWhenLimitReached; + } + } public static class Pool { diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/task/TaskExecutorConfigurations.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/task/TaskExecutorConfigurations.java index 6c07757aa32..8de9c42bb25 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/task/TaskExecutorConfigurations.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/task/TaskExecutorConfigurations.java @@ -136,6 +136,7 @@ class TaskExecutorConfigurations { builder = builder.taskDecorator(this.taskDecorator.getIfUnique()); TaskExecutionProperties.Simple simple = this.properties.getSimple(); builder = builder.concurrencyLimit(simple.getConcurrencyLimit()); + builder = builder.rejectTasksWhenLimitReached(simple.isRejectTasksWhenLimitReached()); TaskExecutionProperties.Shutdown shutdown = this.properties.getShutdown(); if (shutdown.isAwaitTermination()) { builder = builder.taskTerminationTimeout(shutdown.getAwaitTerminationPeriod()); diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/task/TaskExecutionAutoConfigurationTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/task/TaskExecutionAutoConfigurationTests.java index bb2bfad8ed4..51b2e997f38 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/task/TaskExecutionAutoConfigurationTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/task/TaskExecutionAutoConfigurationTests.java @@ -84,10 +84,12 @@ class TaskExecutionAutoConfigurationTests { this.contextRunner .withPropertyValues("spring.task.execution.thread-name-prefix=mytest-", "spring.task.execution.simple.concurrency-limit=1", + "spring.task.execution.simple.reject-tasks-when-limit-reached=true", "spring.task.execution.shutdown.await-termination=true", "spring.task.execution.shutdown.await-termination-period=30s") .run(assertSimpleAsyncTaskExecutor((taskExecutor) -> { assertThat(taskExecutor.getConcurrencyLimit()).isEqualTo(1); + assertThat(taskExecutor).hasFieldOrPropertyWithValue("rejectTasksWhenLimitReached", true); assertThat(taskExecutor.getThreadNamePrefix()).isEqualTo("mytest-"); assertThat(taskExecutor).hasFieldOrPropertyWithValue("taskTerminationTimeout", 30000L); })); diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/task/SimpleAsyncTaskExecutorBuilder.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/task/SimpleAsyncTaskExecutorBuilder.java index e96c791329c..de52d0d41d9 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/task/SimpleAsyncTaskExecutorBuilder.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/task/SimpleAsyncTaskExecutorBuilder.java @@ -41,6 +41,7 @@ import org.springframework.util.CollectionUtils; * @author Stephane Nicoll * @author Filip Hrisafov * @author Moritz Halbritter + * @author Yanming Zhou * @since 3.2.0 */ public class SimpleAsyncTaskExecutorBuilder { @@ -51,6 +52,8 @@ public class SimpleAsyncTaskExecutorBuilder { private final Integer concurrencyLimit; + private final boolean rejectTasksWhenLimitReached; + private final TaskDecorator taskDecorator; private final Set customizers; @@ -58,15 +61,16 @@ public class SimpleAsyncTaskExecutorBuilder { private final Duration taskTerminationTimeout; public SimpleAsyncTaskExecutorBuilder() { - this(null, null, null, null, null, null); + this(null, null, null, false, null, null, null); } private SimpleAsyncTaskExecutorBuilder(Boolean virtualThreads, String threadNamePrefix, Integer concurrencyLimit, - TaskDecorator taskDecorator, Set customizers, - Duration taskTerminationTimeout) { + boolean rejectTasksWhenLimitReached, TaskDecorator taskDecorator, + Set customizers, Duration taskTerminationTimeout) { this.virtualThreads = virtualThreads; this.threadNamePrefix = threadNamePrefix; this.concurrencyLimit = concurrencyLimit; + this.rejectTasksWhenLimitReached = rejectTasksWhenLimitReached; this.taskDecorator = taskDecorator; this.customizers = customizers; this.taskTerminationTimeout = taskTerminationTimeout; @@ -79,7 +83,7 @@ public class SimpleAsyncTaskExecutorBuilder { */ public SimpleAsyncTaskExecutorBuilder threadNamePrefix(String threadNamePrefix) { return new SimpleAsyncTaskExecutorBuilder(this.virtualThreads, threadNamePrefix, this.concurrencyLimit, - this.taskDecorator, this.customizers, this.taskTerminationTimeout); + this.rejectTasksWhenLimitReached, this.taskDecorator, this.customizers, this.taskTerminationTimeout); } /** @@ -89,7 +93,7 @@ public class SimpleAsyncTaskExecutorBuilder { */ public SimpleAsyncTaskExecutorBuilder virtualThreads(Boolean virtualThreads) { return new SimpleAsyncTaskExecutorBuilder(virtualThreads, this.threadNamePrefix, this.concurrencyLimit, - this.taskDecorator, this.customizers, this.taskTerminationTimeout); + this.rejectTasksWhenLimitReached, this.taskDecorator, this.customizers, this.taskTerminationTimeout); } /** @@ -99,7 +103,19 @@ public class SimpleAsyncTaskExecutorBuilder { */ public SimpleAsyncTaskExecutorBuilder concurrencyLimit(Integer concurrencyLimit) { return new SimpleAsyncTaskExecutorBuilder(this.virtualThreads, this.threadNamePrefix, concurrencyLimit, - this.taskDecorator, this.customizers, this.taskTerminationTimeout); + this.rejectTasksWhenLimitReached, this.taskDecorator, this.customizers, this.taskTerminationTimeout); + } + + /** + * Specify whether to reject tasks when the concurrency limit has been reached. + * @param rejectTasksWhenLimitReached whether to reject tasks when the concurrency + * limit has been reached + * @return a new builder instance + * @since 3.5.0 + */ + public SimpleAsyncTaskExecutorBuilder rejectTasksWhenLimitReached(boolean rejectTasksWhenLimitReached) { + return new SimpleAsyncTaskExecutorBuilder(this.virtualThreads, this.threadNamePrefix, this.concurrencyLimit, + rejectTasksWhenLimitReached, this.taskDecorator, this.customizers, this.taskTerminationTimeout); } /** @@ -109,7 +125,7 @@ public class SimpleAsyncTaskExecutorBuilder { */ public SimpleAsyncTaskExecutorBuilder taskDecorator(TaskDecorator taskDecorator) { return new SimpleAsyncTaskExecutorBuilder(this.virtualThreads, this.threadNamePrefix, this.concurrencyLimit, - taskDecorator, this.customizers, this.taskTerminationTimeout); + this.rejectTasksWhenLimitReached, taskDecorator, this.customizers, this.taskTerminationTimeout); } /** @@ -120,7 +136,7 @@ public class SimpleAsyncTaskExecutorBuilder { */ public SimpleAsyncTaskExecutorBuilder taskTerminationTimeout(Duration taskTerminationTimeout) { return new SimpleAsyncTaskExecutorBuilder(this.virtualThreads, this.threadNamePrefix, this.concurrencyLimit, - this.taskDecorator, this.customizers, taskTerminationTimeout); + this.rejectTasksWhenLimitReached, this.taskDecorator, this.customizers, taskTerminationTimeout); } /** @@ -150,7 +166,8 @@ public class SimpleAsyncTaskExecutorBuilder { Iterable customizers) { Assert.notNull(customizers, "'customizers' must not be null"); return new SimpleAsyncTaskExecutorBuilder(this.virtualThreads, this.threadNamePrefix, this.concurrencyLimit, - this.taskDecorator, append(null, customizers), this.taskTerminationTimeout); + this.rejectTasksWhenLimitReached, this.taskDecorator, append(null, customizers), + this.taskTerminationTimeout); } /** @@ -178,7 +195,8 @@ public class SimpleAsyncTaskExecutorBuilder { Iterable customizers) { Assert.notNull(customizers, "'customizers' must not be null"); return new SimpleAsyncTaskExecutorBuilder(this.virtualThreads, this.threadNamePrefix, this.concurrencyLimit, - this.taskDecorator, append(this.customizers, customizers), this.taskTerminationTimeout); + this.rejectTasksWhenLimitReached, this.taskDecorator, append(this.customizers, customizers), + this.taskTerminationTimeout); } /** @@ -218,6 +236,7 @@ public class SimpleAsyncTaskExecutorBuilder { map.from(this.virtualThreads).to(taskExecutor::setVirtualThreads); map.from(this.threadNamePrefix).whenHasText().to(taskExecutor::setThreadNamePrefix); map.from(this.concurrencyLimit).to(taskExecutor::setConcurrencyLimit); + map.from(this.rejectTasksWhenLimitReached).to(taskExecutor::setRejectTasksWhenLimitReached); map.from(this.taskDecorator).to(taskExecutor::setTaskDecorator); map.from(this.taskTerminationTimeout).as(Duration::toMillis).to(taskExecutor::setTaskTerminationTimeout); if (!CollectionUtils.isEmpty(this.customizers)) { diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/task/SimpleAsyncTaskExecutorBuilderTests.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/task/SimpleAsyncTaskExecutorBuilderTests.java index a7f13deb804..4c11847e3a1 100644 --- a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/task/SimpleAsyncTaskExecutorBuilderTests.java +++ b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/task/SimpleAsyncTaskExecutorBuilderTests.java @@ -40,6 +40,7 @@ import static org.mockito.Mockito.spy; * @author Stephane Nicoll * @author Filip Hrisafov * @author Moritz Halbritter + * @author Yanming Zhou */ class SimpleAsyncTaskExecutorBuilderTests { @@ -64,6 +65,12 @@ class SimpleAsyncTaskExecutorBuilderTests { assertThat(executor.getConcurrencyLimit()).isEqualTo(1); } + @Test + void rejectTasksWhenLimitReachedShouldApply() { + SimpleAsyncTaskExecutor executor = this.builder.rejectTasksWhenLimitReached(true).build(); + assertThat(executor).extracting("rejectTasksWhenLimitReached").isEqualTo(true); + } + @Test void taskDecoratorShouldApply() { TaskDecorator taskDecorator = mock(TaskDecorator.class); From 29a07ba277c338de61df2b79524bfe06ad17a747 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Nicoll?= Date: Fri, 11 Apr 2025 12:00:36 +0200 Subject: [PATCH 2/2] Polish contribution See gh-45155 --- .../task/TaskExecutionProperties.java | 24 +++---- .../task/TaskExecutorConfigurations.java | 2 +- .../TaskExecutionAutoConfigurationTests.java | 4 +- .../task/SimpleAsyncTaskExecutorBuilder.java | 72 ++++++++++--------- .../SimpleAsyncTaskExecutorBuilderTests.java | 12 ++-- 5 files changed, 61 insertions(+), 53 deletions(-) diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/task/TaskExecutionProperties.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/task/TaskExecutionProperties.java index fb5ed887d24..8436af58e39 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/task/TaskExecutionProperties.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/task/TaskExecutionProperties.java @@ -77,16 +77,24 @@ public class TaskExecutionProperties { public static class Simple { + /** + * Whether to reject tasks when the concurrency limit has been reached. + */ + private boolean rejectTasksWhenLimitReached; + /** * Set the maximum number of parallel accesses allowed. -1 indicates no * concurrency limit at all. */ private Integer concurrencyLimit; - /** - * Specify whether to reject tasks when the concurrency limit has been reached. - */ - private boolean rejectTasksWhenLimitReached; + public boolean isRejectTasksWhenLimitReached() { + return this.rejectTasksWhenLimitReached; + } + + public void setRejectTasksWhenLimitReached(boolean rejectTasksWhenLimitReached) { + this.rejectTasksWhenLimitReached = rejectTasksWhenLimitReached; + } public Integer getConcurrencyLimit() { return this.concurrencyLimit; @@ -96,14 +104,6 @@ public class TaskExecutionProperties { this.concurrencyLimit = concurrencyLimit; } - public boolean isRejectTasksWhenLimitReached() { - return this.rejectTasksWhenLimitReached; - } - - public void setRejectTasksWhenLimitReached(boolean rejectTasksWhenLimitReached) { - this.rejectTasksWhenLimitReached = rejectTasksWhenLimitReached; - } - } public static class Pool { diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/task/TaskExecutorConfigurations.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/task/TaskExecutorConfigurations.java index 8de9c42bb25..776f16ccda5 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/task/TaskExecutorConfigurations.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/task/TaskExecutorConfigurations.java @@ -135,8 +135,8 @@ class TaskExecutorConfigurations { builder = builder.customizers(this.taskExecutorCustomizers.orderedStream()::iterator); builder = builder.taskDecorator(this.taskDecorator.getIfUnique()); TaskExecutionProperties.Simple simple = this.properties.getSimple(); - builder = builder.concurrencyLimit(simple.getConcurrencyLimit()); builder = builder.rejectTasksWhenLimitReached(simple.isRejectTasksWhenLimitReached()); + builder = builder.concurrencyLimit(simple.getConcurrencyLimit()); TaskExecutionProperties.Shutdown shutdown = this.properties.getShutdown(); if (shutdown.isAwaitTermination()) { builder = builder.taskTerminationTimeout(shutdown.getAwaitTerminationPeriod()); diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/task/TaskExecutionAutoConfigurationTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/task/TaskExecutionAutoConfigurationTests.java index 51b2e997f38..7ab22fc6cfa 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/task/TaskExecutionAutoConfigurationTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/task/TaskExecutionAutoConfigurationTests.java @@ -83,13 +83,13 @@ class TaskExecutionAutoConfigurationTests { void simpleAsyncTaskExecutorBuilderShouldReadProperties() { this.contextRunner .withPropertyValues("spring.task.execution.thread-name-prefix=mytest-", - "spring.task.execution.simple.concurrency-limit=1", "spring.task.execution.simple.reject-tasks-when-limit-reached=true", + "spring.task.execution.simple.concurrency-limit=1", "spring.task.execution.shutdown.await-termination=true", "spring.task.execution.shutdown.await-termination-period=30s") .run(assertSimpleAsyncTaskExecutor((taskExecutor) -> { - assertThat(taskExecutor.getConcurrencyLimit()).isEqualTo(1); assertThat(taskExecutor).hasFieldOrPropertyWithValue("rejectTasksWhenLimitReached", true); + assertThat(taskExecutor.getConcurrencyLimit()).isEqualTo(1); assertThat(taskExecutor.getThreadNamePrefix()).isEqualTo("mytest-"); assertThat(taskExecutor).hasFieldOrPropertyWithValue("taskTerminationTimeout", 30000L); })); diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/task/SimpleAsyncTaskExecutorBuilder.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/task/SimpleAsyncTaskExecutorBuilder.java index de52d0d41d9..403199ce280 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/task/SimpleAsyncTaskExecutorBuilder.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/task/SimpleAsyncTaskExecutorBuilder.java @@ -50,10 +50,10 @@ public class SimpleAsyncTaskExecutorBuilder { private final String threadNamePrefix; - private final Integer concurrencyLimit; - private final boolean rejectTasksWhenLimitReached; + private final Integer concurrencyLimit; + private final TaskDecorator taskDecorator; private final Set customizers; @@ -61,16 +61,16 @@ public class SimpleAsyncTaskExecutorBuilder { private final Duration taskTerminationTimeout; public SimpleAsyncTaskExecutorBuilder() { - this(null, null, null, false, null, null, null); + this(null, null, false, null, null, null, null); } - private SimpleAsyncTaskExecutorBuilder(Boolean virtualThreads, String threadNamePrefix, Integer concurrencyLimit, - boolean rejectTasksWhenLimitReached, TaskDecorator taskDecorator, + private SimpleAsyncTaskExecutorBuilder(Boolean virtualThreads, String threadNamePrefix, + boolean rejectTasksWhenLimitReached, Integer concurrencyLimit, TaskDecorator taskDecorator, Set customizers, Duration taskTerminationTimeout) { this.virtualThreads = virtualThreads; this.threadNamePrefix = threadNamePrefix; - this.concurrencyLimit = concurrencyLimit; this.rejectTasksWhenLimitReached = rejectTasksWhenLimitReached; + this.concurrencyLimit = concurrencyLimit; this.taskDecorator = taskDecorator; this.customizers = customizers; this.taskTerminationTimeout = taskTerminationTimeout; @@ -82,8 +82,9 @@ public class SimpleAsyncTaskExecutorBuilder { * @return a new builder instance */ public SimpleAsyncTaskExecutorBuilder threadNamePrefix(String threadNamePrefix) { - return new SimpleAsyncTaskExecutorBuilder(this.virtualThreads, threadNamePrefix, this.concurrencyLimit, - this.rejectTasksWhenLimitReached, this.taskDecorator, this.customizers, this.taskTerminationTimeout); + return new SimpleAsyncTaskExecutorBuilder(this.virtualThreads, threadNamePrefix, + this.rejectTasksWhenLimitReached, this.concurrencyLimit, this.taskDecorator, this.customizers, + this.taskTerminationTimeout); } /** @@ -92,30 +93,35 @@ public class SimpleAsyncTaskExecutorBuilder { * @return a new builder instance */ public SimpleAsyncTaskExecutorBuilder virtualThreads(Boolean virtualThreads) { - return new SimpleAsyncTaskExecutorBuilder(virtualThreads, this.threadNamePrefix, this.concurrencyLimit, - this.rejectTasksWhenLimitReached, this.taskDecorator, this.customizers, this.taskTerminationTimeout); + return new SimpleAsyncTaskExecutorBuilder(virtualThreads, this.threadNamePrefix, + this.rejectTasksWhenLimitReached, this.concurrencyLimit, this.taskDecorator, this.customizers, + this.taskTerminationTimeout); } /** - * Set the concurrency limit. - * @param concurrencyLimit the concurrency limit + * Set whether to reject tasks when the concurrency limit has been reached. By default + * {@code false} to block the caller until the submission can be accepted. Switch to + * {@code true} for immediate rejection instead. + * @param rejectTasksWhenLimitReached whether to reject tasks when the concurrency + * limit has been reached * @return a new builder instance + * @since 3.5.0 */ - public SimpleAsyncTaskExecutorBuilder concurrencyLimit(Integer concurrencyLimit) { - return new SimpleAsyncTaskExecutorBuilder(this.virtualThreads, this.threadNamePrefix, concurrencyLimit, - this.rejectTasksWhenLimitReached, this.taskDecorator, this.customizers, this.taskTerminationTimeout); + public SimpleAsyncTaskExecutorBuilder rejectTasksWhenLimitReached(boolean rejectTasksWhenLimitReached) { + return new SimpleAsyncTaskExecutorBuilder(this.virtualThreads, this.threadNamePrefix, + rejectTasksWhenLimitReached, this.concurrencyLimit, this.taskDecorator, this.customizers, + this.taskTerminationTimeout); } /** - * Specify whether to reject tasks when the concurrency limit has been reached. - * @param rejectTasksWhenLimitReached whether to reject tasks when the concurrency - * limit has been reached + * Set the concurrency limit. + * @param concurrencyLimit the concurrency limit * @return a new builder instance - * @since 3.5.0 */ - public SimpleAsyncTaskExecutorBuilder rejectTasksWhenLimitReached(boolean rejectTasksWhenLimitReached) { - return new SimpleAsyncTaskExecutorBuilder(this.virtualThreads, this.threadNamePrefix, this.concurrencyLimit, - rejectTasksWhenLimitReached, this.taskDecorator, this.customizers, this.taskTerminationTimeout); + public SimpleAsyncTaskExecutorBuilder concurrencyLimit(Integer concurrencyLimit) { + return new SimpleAsyncTaskExecutorBuilder(this.virtualThreads, this.threadNamePrefix, + this.rejectTasksWhenLimitReached, concurrencyLimit, this.taskDecorator, this.customizers, + this.taskTerminationTimeout); } /** @@ -124,8 +130,9 @@ public class SimpleAsyncTaskExecutorBuilder { * @return a new builder instance */ public SimpleAsyncTaskExecutorBuilder taskDecorator(TaskDecorator taskDecorator) { - return new SimpleAsyncTaskExecutorBuilder(this.virtualThreads, this.threadNamePrefix, this.concurrencyLimit, - this.rejectTasksWhenLimitReached, taskDecorator, this.customizers, this.taskTerminationTimeout); + return new SimpleAsyncTaskExecutorBuilder(this.virtualThreads, this.threadNamePrefix, + this.rejectTasksWhenLimitReached, this.concurrencyLimit, taskDecorator, this.customizers, + this.taskTerminationTimeout); } /** @@ -135,8 +142,9 @@ public class SimpleAsyncTaskExecutorBuilder { * @since 3.2.1 */ public SimpleAsyncTaskExecutorBuilder taskTerminationTimeout(Duration taskTerminationTimeout) { - return new SimpleAsyncTaskExecutorBuilder(this.virtualThreads, this.threadNamePrefix, this.concurrencyLimit, - this.rejectTasksWhenLimitReached, this.taskDecorator, this.customizers, taskTerminationTimeout); + return new SimpleAsyncTaskExecutorBuilder(this.virtualThreads, this.threadNamePrefix, + this.rejectTasksWhenLimitReached, this.concurrencyLimit, this.taskDecorator, this.customizers, + taskTerminationTimeout); } /** @@ -165,8 +173,8 @@ public class SimpleAsyncTaskExecutorBuilder { public SimpleAsyncTaskExecutorBuilder customizers( Iterable customizers) { Assert.notNull(customizers, "'customizers' must not be null"); - return new SimpleAsyncTaskExecutorBuilder(this.virtualThreads, this.threadNamePrefix, this.concurrencyLimit, - this.rejectTasksWhenLimitReached, this.taskDecorator, append(null, customizers), + return new SimpleAsyncTaskExecutorBuilder(this.virtualThreads, this.threadNamePrefix, + this.rejectTasksWhenLimitReached, this.concurrencyLimit, this.taskDecorator, append(null, customizers), this.taskTerminationTimeout); } @@ -194,9 +202,9 @@ public class SimpleAsyncTaskExecutorBuilder { public SimpleAsyncTaskExecutorBuilder additionalCustomizers( Iterable customizers) { Assert.notNull(customizers, "'customizers' must not be null"); - return new SimpleAsyncTaskExecutorBuilder(this.virtualThreads, this.threadNamePrefix, this.concurrencyLimit, - this.rejectTasksWhenLimitReached, this.taskDecorator, append(this.customizers, customizers), - this.taskTerminationTimeout); + return new SimpleAsyncTaskExecutorBuilder(this.virtualThreads, this.threadNamePrefix, + this.rejectTasksWhenLimitReached, this.concurrencyLimit, this.taskDecorator, + append(this.customizers, customizers), this.taskTerminationTimeout); } /** @@ -235,8 +243,8 @@ public class SimpleAsyncTaskExecutorBuilder { PropertyMapper map = PropertyMapper.get().alwaysApplyingWhenNonNull(); map.from(this.virtualThreads).to(taskExecutor::setVirtualThreads); map.from(this.threadNamePrefix).whenHasText().to(taskExecutor::setThreadNamePrefix); - map.from(this.concurrencyLimit).to(taskExecutor::setConcurrencyLimit); map.from(this.rejectTasksWhenLimitReached).to(taskExecutor::setRejectTasksWhenLimitReached); + map.from(this.concurrencyLimit).to(taskExecutor::setConcurrencyLimit); map.from(this.taskDecorator).to(taskExecutor::setTaskDecorator); map.from(this.taskTerminationTimeout).as(Duration::toMillis).to(taskExecutor::setTaskTerminationTimeout); if (!CollectionUtils.isEmpty(this.customizers)) { diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/task/SimpleAsyncTaskExecutorBuilderTests.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/task/SimpleAsyncTaskExecutorBuilderTests.java index 4c11847e3a1..eb09d5aa944 100644 --- a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/task/SimpleAsyncTaskExecutorBuilderTests.java +++ b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/task/SimpleAsyncTaskExecutorBuilderTests.java @@ -59,18 +59,18 @@ class SimpleAsyncTaskExecutorBuilderTests { SimpleAsyncTaskExecutorAssert.assertThat(executor).usesVirtualThreads(); } - @Test - void concurrencyLimitShouldApply() { - SimpleAsyncTaskExecutor executor = this.builder.concurrencyLimit(1).build(); - assertThat(executor.getConcurrencyLimit()).isEqualTo(1); - } - @Test void rejectTasksWhenLimitReachedShouldApply() { SimpleAsyncTaskExecutor executor = this.builder.rejectTasksWhenLimitReached(true).build(); assertThat(executor).extracting("rejectTasksWhenLimitReached").isEqualTo(true); } + @Test + void concurrencyLimitShouldApply() { + SimpleAsyncTaskExecutor executor = this.builder.concurrencyLimit(1).build(); + assertThat(executor.getConcurrencyLimit()).isEqualTo(1); + } + @Test void taskDecoratorShouldApply() { TaskDecorator taskDecorator = mock(TaskDecorator.class);