Reject late-executing tasks after termination waiting

Closes gh-36362
This commit is contained in:
Juergen Hoeller
2026-02-24 17:17:21 +01:00
parent ab8cb8de6e
commit cff48fff2d
@@ -96,6 +96,8 @@ public class SimpleAsyncTaskExecutor extends CustomizableThreadCreator
private volatile boolean active = true;
private volatile boolean cancelled = false;
/**
* Create a new SimpleAsyncTaskExecutor with default thread name prefix.
@@ -389,6 +391,7 @@ public class SimpleAsyncTaskExecutor extends CustomizableThreadCreator
Set<Thread> threads = this.activeThreads;
if (threads != null) {
if (this.cancelRemainingTasksOnClose) {
this.cancelled = true;
// Early interrupt for remaining tasks on close
threads.forEach(Thread::interrupt);
}
@@ -402,6 +405,7 @@ public class SimpleAsyncTaskExecutor extends CustomizableThreadCreator
catch (InterruptedException ex) {
Thread.currentThread().interrupt();
}
this.cancelled = true;
}
if (!this.cancelRemainingTasksOnClose) {
// Late interrupt for remaining tasks after timeout
@@ -412,6 +416,12 @@ public class SimpleAsyncTaskExecutor extends CustomizableThreadCreator
}
}
private void checkCancelled() {
if (this.cancelled) {
throw new TaskRejectedException(getClass().getSimpleName() + " has cancelled all remaining tasks");
}
}
/**
* Subclass of the general ConcurrencyThrottleSupport class,
@@ -464,16 +474,27 @@ public class SimpleAsyncTaskExecutor extends CustomizableThreadCreator
Thread thread = null;
if (threads != null) {
thread = Thread.currentThread();
threads.add(thread);
if (isActive()) {
threads.add(thread);
}
else {
synchronized (threads) {
checkCancelled();
threads.add(thread);
}
}
}
try {
this.task.run();
}
finally {
if (threads != null) {
threads.remove(thread);
if (!isActive()) {
if (isActive()) {
threads.remove(thread);
}
else {
synchronized (threads) {
threads.remove(thread);
if (threads.isEmpty()) {
threads.notify();
}