From 015beb0058f897bf557b50fc84c6163218f7c800 Mon Sep 17 00:00:00 2001 From: Juergen Hoeller Date: Mon, 28 Oct 2024 22:14:41 +0100 Subject: [PATCH] Provide first-class virtual thread option for common executors Closes gh-33807 --- .../ExecutorConfigurationSupport.java | 28 ++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/spring-context/src/main/java/org/springframework/scheduling/concurrent/ExecutorConfigurationSupport.java b/spring-context/src/main/java/org/springframework/scheduling/concurrent/ExecutorConfigurationSupport.java index 1cfbb58c1c4..99f22d71a09 100644 --- a/spring-context/src/main/java/org/springframework/scheduling/concurrent/ExecutorConfigurationSupport.java +++ b/spring-context/src/main/java/org/springframework/scheduling/concurrent/ExecutorConfigurationSupport.java @@ -36,6 +36,8 @@ import org.springframework.context.ApplicationListener; import org.springframework.context.Lifecycle; import org.springframework.context.SmartLifecycle; import org.springframework.context.event.ContextClosedEvent; +import org.springframework.core.task.SimpleAsyncTaskExecutor; +import org.springframework.core.task.VirtualThreadTaskExecutor; import org.springframework.lang.Nullable; /** @@ -75,6 +77,8 @@ public abstract class ExecutorConfigurationSupport extends CustomizableThreadFac protected final Log logger = LogFactory.getLog(getClass()); + private boolean virtualThreads = false; + private ThreadFactory threadFactory = this; private boolean threadNamePrefixSet = false; @@ -104,6 +108,25 @@ public abstract class ExecutorConfigurationSupport extends CustomizableThreadFac private volatile boolean lateShutdown; + /** + * Specify whether to use virtual threads instead of platform threads. + * This is off by default, setting up a traditional platform thread pool. + *

Set this flag to {@code true} on Java 21 or higher for a tightly + * managed thread pool setup with virtual threads. In contrast to + * {@link SimpleAsyncTaskExecutor}, this is integrated with Spring's + * lifecycle management for stopping and restarting execution threads, + * including an early stop signal for a graceful shutdown arrangement. + *

Specify either this or {@link #setThreadFactory}, not both. + * @since 6.2 + * @see #setThreadFactory + * @see VirtualThreadTaskExecutor#getVirtualThreadFactory() + * @see SimpleAsyncTaskExecutor#setVirtualThreads + */ + public void setVirtualThreads(boolean virtualThreads) { + this.virtualThreads = virtualThreads; + this.threadFactory = this; + } + /** * Set the ThreadFactory to use for the ExecutorService's thread pool. * The default is the underlying ExecutorService's default thread factory. @@ -120,6 +143,7 @@ public abstract class ExecutorConfigurationSupport extends CustomizableThreadFac */ public void setThreadFactory(@Nullable ThreadFactory threadFactory) { this.threadFactory = (threadFactory != null ? threadFactory : this); + this.virtualThreads = false; } @Override @@ -282,7 +306,9 @@ public abstract class ExecutorConfigurationSupport extends CustomizableThreadFac if (!this.threadNamePrefixSet && this.beanName != null) { setThreadNamePrefix(this.beanName + "-"); } - this.executor = initializeExecutor(this.threadFactory, this.rejectedExecutionHandler); + ThreadFactory factory = (this.virtualThreads ? + new VirtualThreadTaskExecutor(getThreadNamePrefix()).getVirtualThreadFactory() : this.threadFactory); + this.executor = initializeExecutor(factory, this.rejectedExecutionHandler); this.lifecycleDelegate = new ExecutorLifecycleDelegate(this.executor); }