Skip to content

Commit 31fb2d2

Browse files
committed
Add virtual thread option for ThreadPoolTaskExecutorBuilder/ThreadPoolTaskSchedulerBuilder
See spring-projects/spring-framework#33807
1 parent 24202a0 commit 31fb2d2

File tree

9 files changed

+184
-45
lines changed

9 files changed

+184
-45
lines changed

Diff for: gradle.properties

+1-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ mavenVersion=3.9.4
1919
mockitoVersion=5.14.2
2020
nativeBuildToolsVersion=0.10.3
2121
snakeYamlVersion=2.3
22-
springFrameworkVersion=6.2.0-RC3
22+
springFrameworkVersion=6.2.0-SNAPSHOT
2323
springFramework60xVersion=6.0.23
2424
tomcatVersion=10.1.31
2525

Diff for: spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/task/TaskExecutorConfigurations.java

+33-11
Original file line numberDiff line numberDiff line change
@@ -69,25 +69,49 @@ ThreadPoolTaskExecutor applicationTaskExecutor(ThreadPoolTaskExecutorBuilder thr
6969
@Configuration(proxyBeanMethods = false)
7070
static class ThreadPoolTaskExecutorBuilderConfiguration {
7171

72-
@Bean
73-
@ConditionalOnMissingBean(ThreadPoolTaskExecutorBuilder.class)
74-
ThreadPoolTaskExecutorBuilder threadPoolTaskExecutorBuilder(TaskExecutionProperties properties,
72+
private final TaskExecutionProperties properties;
73+
74+
private final ObjectProvider<ThreadPoolTaskExecutorCustomizer> threadPoolTaskExecutorCustomizers;
75+
76+
private final ObjectProvider<TaskDecorator> taskDecorator;
77+
78+
ThreadPoolTaskExecutorBuilderConfiguration(TaskExecutionProperties properties,
7579
ObjectProvider<ThreadPoolTaskExecutorCustomizer> threadPoolTaskExecutorCustomizers,
7680
ObjectProvider<TaskDecorator> taskDecorator) {
77-
TaskExecutionProperties.Pool pool = properties.getPool();
81+
this.properties = properties;
82+
this.threadPoolTaskExecutorCustomizers = threadPoolTaskExecutorCustomizers;
83+
this.taskDecorator = taskDecorator;
84+
}
85+
86+
@Bean
87+
@ConditionalOnMissingBean
88+
@ConditionalOnThreading(Threading.PLATFORM)
89+
ThreadPoolTaskExecutorBuilder threadPoolTaskExecutorBuilder() {
90+
return builder();
91+
}
92+
93+
@Bean(name = "threadPoolTaskExecutorBuilder")
94+
@ConditionalOnMissingBean
95+
@ConditionalOnThreading(Threading.VIRTUAL)
96+
ThreadPoolTaskExecutorBuilder threadPoolTaskExecutorBuilderVirtualThreads() {
97+
return builder().virtualThreads(true);
98+
}
99+
100+
private ThreadPoolTaskExecutorBuilder builder() {
101+
TaskExecutionProperties.Pool pool = this.properties.getPool();
78102
ThreadPoolTaskExecutorBuilder builder = new ThreadPoolTaskExecutorBuilder();
79103
builder = builder.queueCapacity(pool.getQueueCapacity());
80104
builder = builder.corePoolSize(pool.getCoreSize());
81105
builder = builder.maxPoolSize(pool.getMaxSize());
82106
builder = builder.allowCoreThreadTimeOut(pool.isAllowCoreThreadTimeout());
83107
builder = builder.keepAlive(pool.getKeepAlive());
84108
builder = builder.acceptTasksAfterContextClose(pool.getShutdown().isAcceptTasksAfterContextClose());
85-
TaskExecutionProperties.Shutdown shutdown = properties.getShutdown();
109+
TaskExecutionProperties.Shutdown shutdown = this.properties.getShutdown();
86110
builder = builder.awaitTermination(shutdown.isAwaitTermination());
87111
builder = builder.awaitTerminationPeriod(shutdown.getAwaitTerminationPeriod());
88-
builder = builder.threadNamePrefix(properties.getThreadNamePrefix());
89-
builder = builder.customizers(threadPoolTaskExecutorCustomizers.orderedStream()::iterator);
90-
builder = builder.taskDecorator(taskDecorator.getIfUnique());
112+
builder = builder.threadNamePrefix(this.properties.getThreadNamePrefix());
113+
builder = builder.customizers(this.threadPoolTaskExecutorCustomizers.orderedStream()::iterator);
114+
builder = builder.taskDecorator(this.taskDecorator.getIfUnique());
91115
return builder;
92116
}
93117

@@ -121,9 +145,7 @@ SimpleAsyncTaskExecutorBuilder simpleAsyncTaskExecutorBuilder() {
121145
@ConditionalOnMissingBean
122146
@ConditionalOnThreading(Threading.VIRTUAL)
123147
SimpleAsyncTaskExecutorBuilder simpleAsyncTaskExecutorBuilderVirtualThreads() {
124-
SimpleAsyncTaskExecutorBuilder builder = builder();
125-
builder = builder.virtualThreads(true);
126-
return builder;
148+
return builder().virtualThreads(true);
127149
}
128150

129151
private SimpleAsyncTaskExecutorBuilder builder() {

Diff for: spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/task/TaskSchedulingConfigurations.java

+30-11
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
* {@link TaskSchedulingAutoConfiguration} in a specific order.
4040
*
4141
* @author Moritz Halbritter
42+
* @author Yanming Zhou
4243
*/
4344
class TaskSchedulingConfigurations {
4445

@@ -64,20 +65,40 @@ ThreadPoolTaskScheduler taskScheduler(ThreadPoolTaskSchedulerBuilder threadPoolT
6465
@Configuration(proxyBeanMethods = false)
6566
static class ThreadPoolTaskSchedulerBuilderConfiguration {
6667

67-
@Bean
68-
@ConditionalOnMissingBean(ThreadPoolTaskSchedulerBuilder.class)
69-
ThreadPoolTaskSchedulerBuilder threadPoolTaskSchedulerBuilder(TaskSchedulingProperties properties,
68+
private final TaskSchedulingProperties properties;
69+
70+
private final ObjectProvider<ThreadPoolTaskSchedulerCustomizer> threadPoolTaskSchedulerCustomizers;
71+
72+
ThreadPoolTaskSchedulerBuilderConfiguration(TaskSchedulingProperties properties,
7073
ObjectProvider<ThreadPoolTaskSchedulerCustomizer> threadPoolTaskSchedulerCustomizers) {
71-
TaskSchedulingProperties.Shutdown shutdown = properties.getShutdown();
74+
this.properties = properties;
75+
this.threadPoolTaskSchedulerCustomizers = threadPoolTaskSchedulerCustomizers;
76+
}
77+
78+
@Bean
79+
@ConditionalOnMissingBean
80+
@ConditionalOnThreading(Threading.PLATFORM)
81+
ThreadPoolTaskSchedulerBuilder threadPoolTaskSchedulerBuilder() {
82+
return builder();
83+
}
84+
85+
@Bean(name = "threadPoolTaskSchedulerBuilder")
86+
@ConditionalOnMissingBean
87+
@ConditionalOnThreading(Threading.VIRTUAL)
88+
ThreadPoolTaskSchedulerBuilder threadPoolTaskSchedulerBuilderVirtualThreads() {
89+
return builder().virtualThreads(true);
90+
}
91+
92+
private ThreadPoolTaskSchedulerBuilder builder() {
93+
TaskSchedulingProperties.Shutdown shutdown = this.properties.getShutdown();
7294
ThreadPoolTaskSchedulerBuilder builder = new ThreadPoolTaskSchedulerBuilder();
73-
builder = builder.poolSize(properties.getPool().getSize());
95+
builder = builder.poolSize(this.properties.getPool().getSize());
7496
builder = builder.awaitTermination(shutdown.isAwaitTermination());
7597
builder = builder.awaitTerminationPeriod(shutdown.getAwaitTerminationPeriod());
76-
builder = builder.threadNamePrefix(properties.getThreadNamePrefix());
77-
builder = builder.customizers(threadPoolTaskSchedulerCustomizers);
98+
builder = builder.threadNamePrefix(this.properties.getThreadNamePrefix());
99+
builder = builder.customizers(this.threadPoolTaskSchedulerCustomizers);
78100
return builder;
79101
}
80-
81102
}
82103

83104
@Configuration(proxyBeanMethods = false)
@@ -104,9 +125,7 @@ SimpleAsyncTaskSchedulerBuilder simpleAsyncTaskSchedulerBuilder() {
104125
@ConditionalOnMissingBean
105126
@ConditionalOnThreading(Threading.VIRTUAL)
106127
SimpleAsyncTaskSchedulerBuilder simpleAsyncTaskSchedulerBuilderVirtualThreads() {
107-
SimpleAsyncTaskSchedulerBuilder builder = builder();
108-
builder = builder.virtualThreads(true);
109-
return builder;
128+
return builder().virtualThreads(true);
110129
}
111130

112131
private SimpleAsyncTaskSchedulerBuilder builder() {

Diff for: spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/task/TaskExecutionAutoConfigurationTests.java

+17
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,23 @@ void threadPoolTaskExecutorBuilderShouldUseTaskDecorator() {
128128
});
129129
}
130130

131+
@Test
132+
void threadPoolTaskExecutorBuilderUsesPlatformThreadsByDefault() {
133+
this.contextRunner.run((context) -> {
134+
ThreadPoolTaskExecutorBuilder builder = context.getBean(ThreadPoolTaskExecutorBuilder.class);
135+
assertThat(builder).hasFieldOrPropertyWithValue("virtualThreads", null);
136+
});
137+
}
138+
139+
@Test
140+
@EnabledForJreRange(min = JRE.JAVA_21)
141+
void threadPoolTaskExecutorBuilderUsesVirtualThreadsWhenEnabled() {
142+
this.contextRunner.withPropertyValues("spring.threads.virtual.enabled=true").run((context) -> {
143+
ThreadPoolTaskExecutorBuilder builder = context.getBean(ThreadPoolTaskExecutorBuilder.class);
144+
assertThat(builder).hasFieldOrPropertyWithValue("virtualThreads", true);
145+
});
146+
}
147+
131148
@Test
132149
void whenThreadPoolTaskExecutorIsAutoConfiguredThenItIsLazy() {
133150
this.contextRunner.run((context) -> {

Diff for: spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/task/TaskSchedulingAutoConfigurationTests.java

+23
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@
5656
*
5757
* @author Stephane Nicoll
5858
* @author Moritz Halbritter
59+
* @author Yanming Zhou
5960
*/
6061
class TaskSchedulingAutoConfigurationTests {
6162

@@ -100,6 +101,28 @@ void enableSchedulingWithNoTaskExecutorAutoConfiguresOne() {
100101
});
101102
}
102103

104+
@Test
105+
@EnabledForJreRange(min = JRE.JAVA_21)
106+
void threadPoolTaskSchedulerBuilderShouldUseVirtualThreadsIfEnabled() {
107+
this.contextRunner.withPropertyValues("spring.threads.virtual.enabled=true")
108+
.withUserConfiguration(SchedulingConfiguration.class)
109+
.run((context) -> {
110+
assertThat(context).hasSingleBean(ThreadPoolTaskSchedulerBuilder.class);
111+
ThreadPoolTaskSchedulerBuilder builder = context.getBean(ThreadPoolTaskSchedulerBuilder.class);
112+
assertThat(builder).hasFieldOrPropertyWithValue("virtualThreads", true);
113+
});
114+
}
115+
116+
@Test
117+
@EnabledForJreRange(min = JRE.JAVA_21)
118+
void threadPoolTaskSchedulerBuilderShouldUsePlatformThreadsByDefault() {
119+
this.contextRunner.withUserConfiguration(SchedulingConfiguration.class).run((context) -> {
120+
assertThat(context).hasSingleBean(ThreadPoolTaskSchedulerBuilder.class);
121+
ThreadPoolTaskSchedulerBuilder builder = context.getBean(ThreadPoolTaskSchedulerBuilder.class);
122+
assertThat(builder).hasFieldOrPropertyWithValue("virtualThreads", null);
123+
});
124+
}
125+
103126
@Test
104127
void simpleAsyncTaskSchedulerBuilderShouldReadProperties() {
105128
this.contextRunner

Diff for: spring-boot-project/spring-boot/src/main/java/org/springframework/boot/task/ThreadPoolTaskExecutorBuilder.java

+41-13
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,8 @@ public class ThreadPoolTaskExecutorBuilder {
6565

6666
private final TaskDecorator taskDecorator;
6767

68+
private final Boolean virtualThreads;
69+
6870
private final Set<ThreadPoolTaskExecutorCustomizer> customizers;
6971

7072
public ThreadPoolTaskExecutorBuilder() {
@@ -78,13 +80,14 @@ public ThreadPoolTaskExecutorBuilder() {
7880
this.awaitTerminationPeriod = null;
7981
this.threadNamePrefix = null;
8082
this.taskDecorator = null;
83+
this.virtualThreads = null;
8184
this.customizers = null;
8285
}
8386

8487
private ThreadPoolTaskExecutorBuilder(Integer queueCapacity, Integer corePoolSize, Integer maxPoolSize,
8588
Boolean allowCoreThreadTimeOut, Duration keepAlive, Boolean acceptTasksAfterContextClose,
8689
Boolean awaitTermination, Duration awaitTerminationPeriod, String threadNamePrefix,
87-
TaskDecorator taskDecorator, Set<ThreadPoolTaskExecutorCustomizer> customizers) {
90+
TaskDecorator taskDecorator, Boolean virtualThreads, Set<ThreadPoolTaskExecutorCustomizer> customizers) {
8891
this.queueCapacity = queueCapacity;
8992
this.corePoolSize = corePoolSize;
9093
this.maxPoolSize = maxPoolSize;
@@ -95,6 +98,7 @@ private ThreadPoolTaskExecutorBuilder(Integer queueCapacity, Integer corePoolSiz
9598
this.awaitTerminationPeriod = awaitTerminationPeriod;
9699
this.threadNamePrefix = threadNamePrefix;
97100
this.taskDecorator = taskDecorator;
101+
this.virtualThreads = virtualThreads;
98102
this.customizers = customizers;
99103
}
100104

@@ -107,7 +111,8 @@ private ThreadPoolTaskExecutorBuilder(Integer queueCapacity, Integer corePoolSiz
107111
public ThreadPoolTaskExecutorBuilder queueCapacity(int queueCapacity) {
108112
return new ThreadPoolTaskExecutorBuilder(queueCapacity, this.corePoolSize, this.maxPoolSize,
109113
this.allowCoreThreadTimeOut, this.keepAlive, this.acceptTasksAfterContextClose, this.awaitTermination,
110-
this.awaitTerminationPeriod, this.threadNamePrefix, this.taskDecorator, this.customizers);
114+
this.awaitTerminationPeriod, this.threadNamePrefix, this.taskDecorator, this.virtualThreads,
115+
this.customizers);
111116
}
112117

113118
/**
@@ -122,7 +127,8 @@ public ThreadPoolTaskExecutorBuilder queueCapacity(int queueCapacity) {
122127
public ThreadPoolTaskExecutorBuilder corePoolSize(int corePoolSize) {
123128
return new ThreadPoolTaskExecutorBuilder(this.queueCapacity, corePoolSize, this.maxPoolSize,
124129
this.allowCoreThreadTimeOut, this.keepAlive, this.acceptTasksAfterContextClose, this.awaitTermination,
125-
this.awaitTerminationPeriod, this.threadNamePrefix, this.taskDecorator, this.customizers);
130+
this.awaitTerminationPeriod, this.threadNamePrefix, this.taskDecorator, this.virtualThreads,
131+
this.customizers);
126132
}
127133

128134
/**
@@ -137,7 +143,8 @@ public ThreadPoolTaskExecutorBuilder corePoolSize(int corePoolSize) {
137143
public ThreadPoolTaskExecutorBuilder maxPoolSize(int maxPoolSize) {
138144
return new ThreadPoolTaskExecutorBuilder(this.queueCapacity, this.corePoolSize, maxPoolSize,
139145
this.allowCoreThreadTimeOut, this.keepAlive, this.acceptTasksAfterContextClose, this.awaitTermination,
140-
this.awaitTerminationPeriod, this.threadNamePrefix, this.taskDecorator, this.customizers);
146+
this.awaitTerminationPeriod, this.threadNamePrefix, this.taskDecorator, this.virtualThreads,
147+
this.customizers);
141148
}
142149

143150
/**
@@ -149,7 +156,8 @@ public ThreadPoolTaskExecutorBuilder maxPoolSize(int maxPoolSize) {
149156
public ThreadPoolTaskExecutorBuilder allowCoreThreadTimeOut(boolean allowCoreThreadTimeOut) {
150157
return new ThreadPoolTaskExecutorBuilder(this.queueCapacity, this.corePoolSize, this.maxPoolSize,
151158
allowCoreThreadTimeOut, this.keepAlive, this.acceptTasksAfterContextClose, this.awaitTermination,
152-
this.awaitTerminationPeriod, this.threadNamePrefix, this.taskDecorator, this.customizers);
159+
this.awaitTerminationPeriod, this.threadNamePrefix, this.taskDecorator, this.virtualThreads,
160+
this.customizers);
153161
}
154162

155163
/**
@@ -160,7 +168,8 @@ public ThreadPoolTaskExecutorBuilder allowCoreThreadTimeOut(boolean allowCoreThr
160168
public ThreadPoolTaskExecutorBuilder keepAlive(Duration keepAlive) {
161169
return new ThreadPoolTaskExecutorBuilder(this.queueCapacity, this.corePoolSize, this.maxPoolSize,
162170
this.allowCoreThreadTimeOut, keepAlive, this.acceptTasksAfterContextClose, this.awaitTermination,
163-
this.awaitTerminationPeriod, this.threadNamePrefix, this.taskDecorator, this.customizers);
171+
this.awaitTerminationPeriod, this.threadNamePrefix, this.taskDecorator, this.virtualThreads,
172+
this.customizers);
164173
}
165174

166175
/**
@@ -174,7 +183,8 @@ public ThreadPoolTaskExecutorBuilder keepAlive(Duration keepAlive) {
174183
public ThreadPoolTaskExecutorBuilder acceptTasksAfterContextClose(boolean acceptTasksAfterContextClose) {
175184
return new ThreadPoolTaskExecutorBuilder(this.queueCapacity, this.corePoolSize, this.maxPoolSize,
176185
this.allowCoreThreadTimeOut, this.keepAlive, acceptTasksAfterContextClose, this.awaitTermination,
177-
this.awaitTerminationPeriod, this.threadNamePrefix, this.taskDecorator, this.customizers);
186+
this.awaitTerminationPeriod, this.threadNamePrefix, this.taskDecorator, this.virtualThreads,
187+
this.customizers);
178188
}
179189

180190
/**
@@ -188,7 +198,8 @@ public ThreadPoolTaskExecutorBuilder acceptTasksAfterContextClose(boolean accept
188198
public ThreadPoolTaskExecutorBuilder awaitTermination(boolean awaitTermination) {
189199
return new ThreadPoolTaskExecutorBuilder(this.queueCapacity, this.corePoolSize, this.maxPoolSize,
190200
this.allowCoreThreadTimeOut, this.keepAlive, this.acceptTasksAfterContextClose, awaitTermination,
191-
this.awaitTerminationPeriod, this.threadNamePrefix, this.taskDecorator, this.customizers);
201+
this.awaitTerminationPeriod, this.threadNamePrefix, this.taskDecorator, this.virtualThreads,
202+
this.customizers);
192203
}
193204

194205
/**
@@ -203,7 +214,8 @@ public ThreadPoolTaskExecutorBuilder awaitTermination(boolean awaitTermination)
203214
public ThreadPoolTaskExecutorBuilder awaitTerminationPeriod(Duration awaitTerminationPeriod) {
204215
return new ThreadPoolTaskExecutorBuilder(this.queueCapacity, this.corePoolSize, this.maxPoolSize,
205216
this.allowCoreThreadTimeOut, this.keepAlive, this.acceptTasksAfterContextClose, this.awaitTermination,
206-
awaitTerminationPeriod, this.threadNamePrefix, this.taskDecorator, this.customizers);
217+
awaitTerminationPeriod, this.threadNamePrefix, this.taskDecorator, this.virtualThreads,
218+
this.customizers);
207219
}
208220

209221
/**
@@ -214,7 +226,8 @@ public ThreadPoolTaskExecutorBuilder awaitTerminationPeriod(Duration awaitTermin
214226
public ThreadPoolTaskExecutorBuilder threadNamePrefix(String threadNamePrefix) {
215227
return new ThreadPoolTaskExecutorBuilder(this.queueCapacity, this.corePoolSize, this.maxPoolSize,
216228
this.allowCoreThreadTimeOut, this.keepAlive, this.acceptTasksAfterContextClose, this.awaitTermination,
217-
this.awaitTerminationPeriod, threadNamePrefix, this.taskDecorator, this.customizers);
229+
this.awaitTerminationPeriod, threadNamePrefix, this.taskDecorator, this.virtualThreads,
230+
this.customizers);
218231
}
219232

220233
/**
@@ -225,7 +238,20 @@ public ThreadPoolTaskExecutorBuilder threadNamePrefix(String threadNamePrefix) {
225238
public ThreadPoolTaskExecutorBuilder taskDecorator(TaskDecorator taskDecorator) {
226239
return new ThreadPoolTaskExecutorBuilder(this.queueCapacity, this.corePoolSize, this.maxPoolSize,
227240
this.allowCoreThreadTimeOut, this.keepAlive, this.acceptTasksAfterContextClose, this.awaitTermination,
228-
this.awaitTerminationPeriod, this.threadNamePrefix, taskDecorator, this.customizers);
241+
this.awaitTerminationPeriod, this.threadNamePrefix, taskDecorator, this.virtualThreads,
242+
this.customizers);
243+
}
244+
245+
/**
246+
* Specify whether to use virtual threads instead of platform threads.
247+
* @param virtualThreads whether to use virtual threads instead of platform threads
248+
* @return a new builder instance
249+
*/
250+
public ThreadPoolTaskExecutorBuilder virtualThreads(boolean virtualThreads) {
251+
return new ThreadPoolTaskExecutorBuilder(this.queueCapacity, this.corePoolSize, this.maxPoolSize,
252+
this.allowCoreThreadTimeOut, this.keepAlive, this.acceptTasksAfterContextClose, this.awaitTermination,
253+
this.awaitTerminationPeriod, this.threadNamePrefix, this.taskDecorator, virtualThreads,
254+
this.customizers);
229255
}
230256

231257
/**
@@ -255,7 +281,8 @@ public ThreadPoolTaskExecutorBuilder customizers(Iterable<? extends ThreadPoolTa
255281
Assert.notNull(customizers, "Customizers must not be null");
256282
return new ThreadPoolTaskExecutorBuilder(this.queueCapacity, this.corePoolSize, this.maxPoolSize,
257283
this.allowCoreThreadTimeOut, this.keepAlive, this.acceptTasksAfterContextClose, this.awaitTermination,
258-
this.awaitTerminationPeriod, this.threadNamePrefix, this.taskDecorator, append(null, customizers));
284+
this.awaitTerminationPeriod, this.threadNamePrefix, this.taskDecorator, this.virtualThreads,
285+
append(null, customizers));
259286
}
260287

261288
/**
@@ -284,7 +311,7 @@ public ThreadPoolTaskExecutorBuilder additionalCustomizers(
284311
Assert.notNull(customizers, "Customizers must not be null");
285312
return new ThreadPoolTaskExecutorBuilder(this.queueCapacity, this.corePoolSize, this.maxPoolSize,
286313
this.allowCoreThreadTimeOut, this.keepAlive, this.acceptTasksAfterContextClose, this.awaitTermination,
287-
this.awaitTerminationPeriod, this.threadNamePrefix, this.taskDecorator,
314+
this.awaitTerminationPeriod, this.threadNamePrefix, this.taskDecorator, this.virtualThreads,
288315
append(this.customizers, customizers));
289316
}
290317

@@ -332,6 +359,7 @@ public <T extends ThreadPoolTaskExecutor> T configure(T taskExecutor) {
332359
map.from(this.awaitTerminationPeriod).as(Duration::toMillis).to(taskExecutor::setAwaitTerminationMillis);
333360
map.from(this.threadNamePrefix).whenHasText().to(taskExecutor::setThreadNamePrefix);
334361
map.from(this.taskDecorator).to(taskExecutor::setTaskDecorator);
362+
map.from(this.virtualThreads).to(taskExecutor::setVirtualThreads);
335363
if (!CollectionUtils.isEmpty(this.customizers)) {
336364
this.customizers.forEach((customizer) -> customizer.customize(taskExecutor));
337365
}

0 commit comments

Comments
 (0)