36
36
import org .springframework .context .Lifecycle ;
37
37
import org .springframework .context .SmartLifecycle ;
38
38
import org .springframework .context .event .ContextClosedEvent ;
39
+ import org .springframework .core .task .SimpleAsyncTaskExecutor ;
40
+ import org .springframework .core .task .VirtualThreadTaskExecutor ;
39
41
import org .springframework .lang .Nullable ;
40
42
41
43
/**
@@ -75,6 +77,8 @@ public abstract class ExecutorConfigurationSupport extends CustomizableThreadFac
75
77
76
78
protected final Log logger = LogFactory .getLog (getClass ());
77
79
80
+ private boolean virtualThreads = false ;
81
+
78
82
private ThreadFactory threadFactory = this ;
79
83
80
84
private boolean threadNamePrefixSet = false ;
@@ -104,6 +108,25 @@ public abstract class ExecutorConfigurationSupport extends CustomizableThreadFac
104
108
private volatile boolean lateShutdown ;
105
109
106
110
111
+ /**
112
+ * Specify whether to use virtual threads instead of platform threads.
113
+ * This is off by default, setting up a traditional platform thread pool.
114
+ * <p>Set this flag to {@code true} on Java 21 or higher for a tightly
115
+ * managed thread pool setup with virtual threads. In contrast to
116
+ * {@link SimpleAsyncTaskExecutor}, this is integrated with Spring's
117
+ * lifecycle management for stopping and restarting execution threads,
118
+ * including an early stop signal for a graceful shutdown arrangement.
119
+ * <p>Specify either this or {@link #setThreadFactory}, not both.
120
+ * @since 6.2
121
+ * @see #setThreadFactory
122
+ * @see VirtualThreadTaskExecutor#getVirtualThreadFactory()
123
+ * @see SimpleAsyncTaskExecutor#setVirtualThreads
124
+ */
125
+ public void setVirtualThreads (boolean virtualThreads ) {
126
+ this .virtualThreads = virtualThreads ;
127
+ this .threadFactory = this ;
128
+ }
129
+
107
130
/**
108
131
* Set the ThreadFactory to use for the ExecutorService's thread pool.
109
132
* The default is the underlying ExecutorService's default thread factory.
@@ -120,6 +143,7 @@ public abstract class ExecutorConfigurationSupport extends CustomizableThreadFac
120
143
*/
121
144
public void setThreadFactory (@ Nullable ThreadFactory threadFactory ) {
122
145
this .threadFactory = (threadFactory != null ? threadFactory : this );
146
+ this .virtualThreads = false ;
123
147
}
124
148
125
149
@ Override
@@ -282,7 +306,9 @@ public void initialize() {
282
306
if (!this .threadNamePrefixSet && this .beanName != null ) {
283
307
setThreadNamePrefix (this .beanName + "-" );
284
308
}
285
- this .executor = initializeExecutor (this .threadFactory , this .rejectedExecutionHandler );
309
+ ThreadFactory factory = (this .virtualThreads ?
310
+ new VirtualThreadTaskExecutor (getThreadNamePrefix ()).getVirtualThreadFactory () : this .threadFactory );
311
+ this .executor = initializeExecutor (factory , this .rejectedExecutionHandler );
286
312
this .lifecycleDelegate = new ExecutorLifecycleDelegate (this .executor );
287
313
}
288
314
0 commit comments