Skip to content

Commit c8b920a

Browse files
committed
Fix SimpleAsyncTaskExecutor virtual thread path
This commit makes sure that the SimpleAsyncTaskExecutor only creates a virtual thread when the virtualThreadDelegate is set, and not an additional kernel thread as well. See gh-30241
1 parent c564725 commit c8b920a

File tree

2 files changed

+17
-3
lines changed

2 files changed

+17
-3
lines changed

spring-core/src/main/java/org/springframework/core/task/SimpleAsyncTaskExecutor.java

+4-3
Original file line numberDiff line numberDiff line change
@@ -260,9 +260,10 @@ protected void doExecute(Runnable task) {
260260
if (this.virtualThreadDelegate != null) {
261261
this.virtualThreadDelegate.startVirtualThread(nextThreadName(), task);
262262
}
263-
264-
Thread thread = (this.threadFactory != null ? this.threadFactory.newThread(task) : createThread(task));
265-
thread.start();
263+
else {
264+
Thread thread = (this.threadFactory != null ? this.threadFactory.newThread(task) : createThread(task));
265+
thread.start();
266+
}
266267
}
267268

268269

spring-core/src/test/java21/org/springframework/core/task/VirtualThreadTaskExecutorTests.java

+13
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616

1717
package org.springframework.core.task;
1818

19+
import java.util.concurrent.atomic.AtomicInteger;
20+
1921
import org.junit.jupiter.api.Test;
2022

2123
import static org.assertj.core.api.Assertions.assertThat;
@@ -34,6 +36,7 @@ void virtualThreadsWithoutName() {
3436
executeAndWait(executor, task, monitor);
3537
assertThat(task.getThreadName()).isEmpty();
3638
assertThat(task.isVirtual()).isTrue();
39+
assertThat(task.runtCount()).isOne();
3740
}
3841

3942
@Test
@@ -44,6 +47,7 @@ void virtualThreadsWithNamePrefix() {
4447
executeAndWait(executor, task, monitor);
4548
assertThat(task.getThreadName()).isEqualTo("test-0");
4649
assertThat(task.isVirtual()).isTrue();
50+
assertThat(task.runtCount()).isOne();
4751
}
4852

4953
@Test
@@ -54,6 +58,7 @@ void simpleWithVirtualThreadFactory() {
5458
executeAndWait(executor, task, monitor);
5559
assertThat(task.getThreadName()).isEqualTo("test");
5660
assertThat(task.isVirtual()).isTrue();
61+
assertThat(task.runtCount()).isOne();
5762
}
5863

5964
@Test
@@ -66,6 +71,7 @@ void simpleWithVirtualThreadFlag() {
6671
executeAndWait(executor, task, monitor);
6772
assertThat(task.getThreadName()).startsWith(customPrefix);
6873
assertThat(task.isVirtual()).isTrue();
74+
assertThat(task.runtCount()).isOne();
6975
}
7076

7177
private void executeAndWait(TaskExecutor executor, Runnable task, Object monitor) {
@@ -115,6 +121,8 @@ public final void run() {
115121

116122
private static final class ThreadNameHarvester extends AbstractNotifyingRunnable {
117123

124+
private final AtomicInteger runCount = new AtomicInteger();
125+
118126
private String threadName;
119127

120128
private boolean virtual;
@@ -131,11 +139,16 @@ public boolean isVirtual() {
131139
return this.virtual;
132140
}
133141

142+
public int runtCount() {
143+
return this.runCount.get();
144+
}
145+
134146
@Override
135147
protected void doRun() {
136148
Thread thread = Thread.currentThread();
137149
this.threadName = thread.getName();
138150
this.virtual = thread.isVirtual();
151+
runCount.incrementAndGet();
139152
}
140153
}
141154

0 commit comments

Comments
 (0)