36
36
import org .springframework .scheduling .Trigger ;
37
37
import org .springframework .scheduling .support .TaskUtils ;
38
38
import org .springframework .util .Assert ;
39
+ import org .springframework .util .ClassUtils ;
39
40
import org .springframework .util .ErrorHandler ;
40
41
import org .springframework .util .concurrent .ListenableFuture ;
41
42
import org .springframework .util .concurrent .ListenableFutureTask ;
56
57
public class ThreadPoolTaskScheduler extends ExecutorConfigurationSupport
57
58
implements AsyncListenableTaskExecutor , SchedulingTaskExecutor , TaskScheduler {
58
59
60
+ // ScheduledThreadPoolExecutor.setRemoveOnCancelPolicy(boolean) only available on JDK 7+
61
+ private static final boolean setRemoveOnCancelPolicyAvailable =
62
+ ClassUtils .hasMethod (ScheduledThreadPoolExecutor .class , "setRemoveOnCancelPolicy" , boolean .class );
63
+
64
+
59
65
private volatile int poolSize = 1 ;
60
66
61
- private volatile Boolean removeOnCancelPolicy ;
67
+ private volatile boolean removeOnCancelPolicy = false ;
62
68
63
69
private volatile ScheduledExecutorService scheduledExecutor ;
64
70
@@ -79,33 +85,42 @@ public void setPoolSize(int poolSize) {
79
85
}
80
86
81
87
/**
82
- * Set the same property on ScheduledExecutorService (JDK 1.7+).
83
- * There is no default. If not set, the executor property is not set.
88
+ * Set the remove-on-cancel mode on {@link ScheduledThreadPoolExecutor} (JDK 7+).
89
+ * <p>Default is {@code false}. If set to {@code true}, the target executor will be
90
+ * switched into remove-on-cancel mode (if possible, with a soft fallback otherwise).
84
91
* <p><b>This setting can be modified at runtime, for example through JMX.</b>
85
92
*/
86
93
public void setRemoveOnCancelPolicy (boolean removeOnCancelPolicy ) {
87
94
this .removeOnCancelPolicy = removeOnCancelPolicy ;
88
- if (this .scheduledExecutor instanceof ScheduledThreadPoolExecutor ) {
95
+ if (setRemoveOnCancelPolicyAvailable && this .scheduledExecutor instanceof ScheduledThreadPoolExecutor ) {
89
96
((ScheduledThreadPoolExecutor ) this .scheduledExecutor ).setRemoveOnCancelPolicy (removeOnCancelPolicy );
90
97
}
98
+ else if (removeOnCancelPolicy && this .scheduledExecutor != null ) {
99
+ logger .info ("Could not apply remove-on-cancel policy - not a Java 7+ ScheduledThreadPoolExecutor" );
100
+ }
91
101
}
92
102
93
103
/**
94
104
* Set a custom {@link ErrorHandler} strategy.
95
105
*/
96
106
public void setErrorHandler (ErrorHandler errorHandler ) {
97
- Assert .notNull (errorHandler , "'errorHandler' must not be null" );
98
107
this .errorHandler = errorHandler ;
99
108
}
100
109
110
+
101
111
@ Override
102
112
protected ExecutorService initializeExecutor (
103
113
ThreadFactory threadFactory , RejectedExecutionHandler rejectedExecutionHandler ) {
104
114
105
115
this .scheduledExecutor = createExecutor (this .poolSize , threadFactory , rejectedExecutionHandler );
106
116
107
- if (this .scheduledExecutor instanceof ScheduledThreadPoolExecutor && this .removeOnCancelPolicy != null ) {
108
- ((ScheduledThreadPoolExecutor ) this .scheduledExecutor ).setRemoveOnCancelPolicy (this .removeOnCancelPolicy );
117
+ if (this .removeOnCancelPolicy ) {
118
+ if (setRemoveOnCancelPolicyAvailable && this .scheduledExecutor instanceof ScheduledThreadPoolExecutor ) {
119
+ ((ScheduledThreadPoolExecutor ) this .scheduledExecutor ).setRemoveOnCancelPolicy (true );
120
+ }
121
+ else {
122
+ logger .info ("Could not apply remove-on-cancel policy - not a Java 7+ ScheduledThreadPoolExecutor" );
123
+ }
109
124
}
110
125
111
126
return this .scheduledExecutor ;
@@ -166,14 +181,17 @@ public int getPoolSize() {
166
181
}
167
182
168
183
/**
169
- * Return the current setting of removeOnCancelPolicy .
170
- * <p>Requires an underlying {@link ScheduledThreadPoolExecutor} and JDK 1.7+ .
184
+ * Return the current setting for the remove-on-cancel mode .
185
+ * <p>Requires an underlying {@link ScheduledThreadPoolExecutor}.
171
186
*/
172
187
public boolean isRemoveOnCancelPolicy () {
173
- if (this .scheduledExecutor == null ) {
174
- // Not initialized yet: return false (the default of the executor)
188
+ if (!setRemoveOnCancelPolicyAvailable ) {
175
189
return false ;
176
190
}
191
+ if (this .scheduledExecutor == null ) {
192
+ // Not initialized yet: return our setting for the time being.
193
+ return this .removeOnCancelPolicy ;
194
+ }
177
195
return getScheduledThreadPoolExecutor ().getRemoveOnCancelPolicy ();
178
196
}
179
197
0 commit comments