Defensively use setRemoveOnCancelPolicy for JDK 6 compatibility
Issue: SPR-12238
(cherry picked from commit e003d21)
This commit is contained in:
@@ -27,6 +27,7 @@ import org.springframework.beans.factory.FactoryBean;
|
||||
import org.springframework.scheduling.support.DelegatingErrorHandlingRunnable;
|
||||
import org.springframework.scheduling.support.TaskUtils;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
|
||||
/**
|
||||
@@ -66,12 +67,17 @@ import org.springframework.util.ObjectUtils;
|
||||
public class ScheduledExecutorFactoryBean extends ExecutorConfigurationSupport
|
||||
implements FactoryBean<ScheduledExecutorService> {
|
||||
|
||||
// ScheduledThreadPoolExecutor.setRemoveOnCancelPolicy(boolean) only available on JDK 7+
|
||||
private static final boolean setRemoveOnCancelPolicyAvailable =
|
||||
ClassUtils.hasMethod(ScheduledThreadPoolExecutor.class, "setRemoveOnCancelPolicy", boolean.class);
|
||||
|
||||
|
||||
private int poolSize = 1;
|
||||
|
||||
private Boolean removeOnCancelPolicy;
|
||||
|
||||
private ScheduledExecutorTask[] scheduledExecutorTasks;
|
||||
|
||||
private boolean removeOnCancelPolicy = false;
|
||||
|
||||
private boolean continueScheduledExecutionAfterException = false;
|
||||
|
||||
private boolean exposeUnconfigurableExecutor = false;
|
||||
@@ -88,14 +94,6 @@ public class ScheduledExecutorFactoryBean extends ExecutorConfigurationSupport
|
||||
this.poolSize = poolSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the same property on ScheduledExecutorService (JDK 1.7+).
|
||||
* There is no default. If not set, the executor property is not set.
|
||||
*/
|
||||
public void setRemoveOnCancelPolicy(boolean removeOnCancelPolicy) {
|
||||
this.removeOnCancelPolicy = removeOnCancelPolicy;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a list of ScheduledExecutorTask objects with the ScheduledExecutorService
|
||||
* that this FactoryBean creates. Depending on each ScheduledExecutorTask's settings,
|
||||
@@ -108,6 +106,15 @@ public class ScheduledExecutorFactoryBean extends ExecutorConfigurationSupport
|
||||
this.scheduledExecutorTasks = scheduledExecutorTasks;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the remove-on-cancel mode on {@link ScheduledThreadPoolExecutor} (JDK 7+).
|
||||
* <p>Default is {@code false}. If set to {@code true}, the target executor will be
|
||||
* switched into remove-on-cancel mode (if possible, with a soft fallback otherwise).
|
||||
*/
|
||||
public void setRemoveOnCancelPolicy(boolean removeOnCancelPolicy) {
|
||||
this.removeOnCancelPolicy = removeOnCancelPolicy;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify whether to continue the execution of a scheduled task
|
||||
* after it threw an exception.
|
||||
@@ -141,8 +148,13 @@ public class ScheduledExecutorFactoryBean extends ExecutorConfigurationSupport
|
||||
ScheduledExecutorService executor =
|
||||
createExecutor(this.poolSize, threadFactory, rejectedExecutionHandler);
|
||||
|
||||
if (executor instanceof ScheduledThreadPoolExecutor && this.removeOnCancelPolicy != null) {
|
||||
((ScheduledThreadPoolExecutor) executor).setRemoveOnCancelPolicy(this.removeOnCancelPolicy);
|
||||
if (this.removeOnCancelPolicy) {
|
||||
if (setRemoveOnCancelPolicyAvailable && executor instanceof ScheduledThreadPoolExecutor) {
|
||||
((ScheduledThreadPoolExecutor) executor).setRemoveOnCancelPolicy(true);
|
||||
}
|
||||
else {
|
||||
logger.info("Could not apply remove-on-cancel policy - not a Java 7+ ScheduledThreadPoolExecutor");
|
||||
}
|
||||
}
|
||||
|
||||
// Register specified ScheduledExecutorTasks, if necessary.
|
||||
|
||||
@@ -36,6 +36,7 @@ import org.springframework.scheduling.TaskScheduler;
|
||||
import org.springframework.scheduling.Trigger;
|
||||
import org.springframework.scheduling.support.TaskUtils;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.ErrorHandler;
|
||||
import org.springframework.util.concurrent.ListenableFuture;
|
||||
import org.springframework.util.concurrent.ListenableFutureTask;
|
||||
@@ -56,9 +57,14 @@ import org.springframework.util.concurrent.ListenableFutureTask;
|
||||
public class ThreadPoolTaskScheduler extends ExecutorConfigurationSupport
|
||||
implements AsyncListenableTaskExecutor, SchedulingTaskExecutor, TaskScheduler {
|
||||
|
||||
// ScheduledThreadPoolExecutor.setRemoveOnCancelPolicy(boolean) only available on JDK 7+
|
||||
private static final boolean setRemoveOnCancelPolicyAvailable =
|
||||
ClassUtils.hasMethod(ScheduledThreadPoolExecutor.class, "setRemoveOnCancelPolicy", boolean.class);
|
||||
|
||||
|
||||
private volatile int poolSize = 1;
|
||||
|
||||
private volatile Boolean removeOnCancelPolicy;
|
||||
private volatile boolean removeOnCancelPolicy = false;
|
||||
|
||||
private volatile ScheduledExecutorService scheduledExecutor;
|
||||
|
||||
@@ -79,33 +85,42 @@ public class ThreadPoolTaskScheduler extends ExecutorConfigurationSupport
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the same property on ScheduledExecutorService (JDK 1.7+).
|
||||
* There is no default. If not set, the executor property is not set.
|
||||
* Set the remove-on-cancel mode on {@link ScheduledThreadPoolExecutor} (JDK 7+).
|
||||
* <p>Default is {@code false}. If set to {@code true}, the target executor will be
|
||||
* switched into remove-on-cancel mode (if possible, with a soft fallback otherwise).
|
||||
* <p><b>This setting can be modified at runtime, for example through JMX.</b>
|
||||
*/
|
||||
public void setRemoveOnCancelPolicy(boolean removeOnCancelPolicy) {
|
||||
this.removeOnCancelPolicy = removeOnCancelPolicy;
|
||||
if (this.scheduledExecutor instanceof ScheduledThreadPoolExecutor) {
|
||||
if (setRemoveOnCancelPolicyAvailable && this.scheduledExecutor instanceof ScheduledThreadPoolExecutor) {
|
||||
((ScheduledThreadPoolExecutor) this.scheduledExecutor).setRemoveOnCancelPolicy(removeOnCancelPolicy);
|
||||
}
|
||||
else if (removeOnCancelPolicy && this.scheduledExecutor != null) {
|
||||
logger.info("Could not apply remove-on-cancel policy - not a Java 7+ ScheduledThreadPoolExecutor");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a custom {@link ErrorHandler} strategy.
|
||||
*/
|
||||
public void setErrorHandler(ErrorHandler errorHandler) {
|
||||
Assert.notNull(errorHandler, "'errorHandler' must not be null");
|
||||
this.errorHandler = errorHandler;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected ExecutorService initializeExecutor(
|
||||
ThreadFactory threadFactory, RejectedExecutionHandler rejectedExecutionHandler) {
|
||||
|
||||
this.scheduledExecutor = createExecutor(this.poolSize, threadFactory, rejectedExecutionHandler);
|
||||
|
||||
if (this.scheduledExecutor instanceof ScheduledThreadPoolExecutor && this.removeOnCancelPolicy != null) {
|
||||
((ScheduledThreadPoolExecutor) this.scheduledExecutor).setRemoveOnCancelPolicy(this.removeOnCancelPolicy);
|
||||
if (this.removeOnCancelPolicy) {
|
||||
if (setRemoveOnCancelPolicyAvailable && this.scheduledExecutor instanceof ScheduledThreadPoolExecutor) {
|
||||
((ScheduledThreadPoolExecutor) this.scheduledExecutor).setRemoveOnCancelPolicy(true);
|
||||
}
|
||||
else {
|
||||
logger.info("Could not apply remove-on-cancel policy - not a Java 7+ ScheduledThreadPoolExecutor");
|
||||
}
|
||||
}
|
||||
|
||||
return this.scheduledExecutor;
|
||||
@@ -166,14 +181,17 @@ public class ThreadPoolTaskScheduler extends ExecutorConfigurationSupport
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the current setting of removeOnCancelPolicy.
|
||||
* <p>Requires an underlying {@link ScheduledThreadPoolExecutor} and JDK 1.7+.
|
||||
* Return the current setting for the remove-on-cancel mode.
|
||||
* <p>Requires an underlying {@link ScheduledThreadPoolExecutor}.
|
||||
*/
|
||||
public boolean isRemoveOnCancelPolicy() {
|
||||
if (this.scheduledExecutor == null) {
|
||||
// Not initialized yet: return false (the default of the executor)
|
||||
if (!setRemoveOnCancelPolicyAvailable) {
|
||||
return false;
|
||||
}
|
||||
if (this.scheduledExecutor == null) {
|
||||
// Not initialized yet: return our setting for the time being.
|
||||
return this.removeOnCancelPolicy;
|
||||
}
|
||||
return getScheduledThreadPoolExecutor().getRemoveOnCancelPolicy();
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user