@@ -86,6 +86,8 @@ public abstract class ExecutorConfigurationSupport extends CustomizableThreadFac
86
86
@ Nullable
87
87
private ExecutorLifecycleDelegate lifecycleDelegate ;
88
88
89
+ private volatile boolean lateShutdown ;
90
+
89
91
90
92
/**
91
93
* Set the ThreadFactory to use for the ExecutorService's thread pool.
@@ -127,8 +129,9 @@ public void setRejectedExecutionHandler(@Nullable RejectedExecutionHandler rejec
127
129
* <p>Default is {@code false} as of 6.1, triggering an early soft shutdown of
128
130
* the executor and therefore rejecting any further task submissions. Switch this
129
131
* to {@code true} in order to let other components submit tasks even during their
130
- * own destruction callbacks, at the expense of a longer shutdown phase.
131
- * This will usually go along with
132
+ * own stop and destruction callbacks, at the expense of a longer shutdown phase.
133
+ * The executor will not go through a coordinated lifecycle stop phase then
134
+ * but rather only stop tasks on its own shutdown. This usually goes along with
132
135
* {@link #setWaitForTasksToCompleteOnShutdown "waitForTasksToCompleteOnShutdown"}.
133
136
* <p>This flag will only have effect when the executor is running in a Spring
134
137
* application context and able to receive the {@link ContextClosedEvent}.
@@ -144,9 +147,13 @@ public void setAcceptTasksAfterContextClose(boolean acceptTasksAfterContextClose
144
147
/**
145
148
* Set whether to wait for scheduled tasks to complete on shutdown,
146
149
* not interrupting running tasks and executing all tasks in the queue.
147
- * <p>Default is {@code false}, shutting down immediately through interrupting
148
- * ongoing tasks and clearing the queue. Switch this flag to {@code true} if
149
- * you prefer fully completed tasks at the expense of a longer shutdown phase.
150
+ * <p>Default is {@code false}, with a coordinated lifecycle stop first (unless
151
+ * {@link #setAcceptTasksAfterContextClose "acceptTasksAfterContextClose"}
152
+ * has been set) and then an immediate shutdown through interrupting ongoing
153
+ * tasks and clearing the queue. Switch this flag to {@code true} if you
154
+ * prefer fully completed tasks at the expense of a longer shutdown phase.
155
+ * The executor will not go through a coordinated lifecycle stop phase then
156
+ * but rather only stop and wait for task completion on its own shutdown.
150
157
* <p>Note that Spring's container shutdown continues while ongoing tasks
151
158
* are being completed. If you want this executor to block and wait for the
152
159
* termination of tasks before the rest of the container continues to shut
@@ -374,7 +381,7 @@ public void start() {
374
381
*/
375
382
@ Override
376
383
public void stop () {
377
- if (this .lifecycleDelegate != null ) {
384
+ if (this .lifecycleDelegate != null && ! this . lateShutdown ) {
378
385
this .lifecycleDelegate .stop ();
379
386
}
380
387
}
@@ -386,9 +393,12 @@ public void stop() {
386
393
*/
387
394
@ Override
388
395
public void stop (Runnable callback ) {
389
- if (this .lifecycleDelegate != null ) {
396
+ if (this .lifecycleDelegate != null && ! this . lateShutdown ) {
390
397
this .lifecycleDelegate .stop (callback );
391
398
}
399
+ else {
400
+ callback .run ();
401
+ }
392
402
}
393
403
394
404
/**
@@ -439,10 +449,16 @@ protected void afterExecute(Runnable task, @Nullable Throwable ex) {
439
449
*/
440
450
@ Override
441
451
public void onApplicationEvent (ContextClosedEvent event ) {
442
- if (event .getApplicationContext () == this .applicationContext && !this .acceptTasksAfterContextClose ) {
443
- // Early shutdown signal: accept no further tasks, let existing tasks complete
444
- // before hitting the actual destruction step in the shutdown() method above.
445
- initiateShutdown ();
452
+ if (event .getApplicationContext () == this .applicationContext ) {
453
+ if (this .acceptTasksAfterContextClose || this .waitForTasksToCompleteOnShutdown ) {
454
+ // Late shutdown without early stop lifecycle.
455
+ this .lateShutdown = true ;
456
+ }
457
+ else {
458
+ // Early shutdown signal: accept no further tasks, let existing tasks complete
459
+ // before hitting the actual destruction step in the shutdown() method above.
460
+ initiateShutdown ();
461
+ }
446
462
}
447
463
}
448
464
0 commit comments