ScheduledExecutorService
ScheduledExecutorService扩展了ExecutorService,可以延迟或者周期性执行任务。
public ScheduledFuture<?> schedule(Runnable command, long delay, TimeUnit unit);
public <V> ScheduledFuture<V> schedule(Callable<V> callable, long delay, TimeUnit unit);
以上两个方法均是延迟一段时间执行任务,仅执行一次。期间可以通过返回的ScheduledFuture取消执行。
public ScheduledFuture<?> scheduleAtFixedRate(Runnable command,
long initialDelay,
long period,
TimeUnit unit);
以上方法延迟一段时间后执行一次任务,然后再每隔一段时间执行一次任务。
以下任意情况都可导致任务停止执行:
- 调用返回值ScheduledFuture的cancel方法。
- Executor终结。
- 任务执行过程中抛出异常。
后续调用ScheduledFuture.isDone方法会返回true。
如果某次任务的执行超过了period,则下次任务会延后执行。
public ScheduledFuture<?> scheduleWithFixedDelay(Runnable command,
long initialDelay,
long delay,
TimeUnit unit);
与scheduleAtFixedRate的不同之处在于,上一次任务执行完毕到下一次任务开始执行,中间间隔delay的时长。
ScheduledThreadPoolExecutor
再来看看实现类:
public class ScheduledThreadPoolExecutor
extends ThreadPoolExecutor
implements ScheduledExecutorService
可以看到ScheduledThreadPoolExecutor扩展了ThreadPoolExecutor,实现了延迟或者周期性执行任务的方法。
ScheduledThreadPoolExecutor中线程的数量固定为corePoolSize,使用无限队列。maximumPoolSize参数无效。另外,不要将corePoolSize设置为0,也不要使用allowCoreThreadTimeOut。
该类是被设计用来替代Timer的,原因有以下几点:
- Timer是单线程的,执行多个任务时,难以保证任务被按时执行;而ScheduledThreadPoolExecutor是多线程的。
- Timer不捕获异常,一个任务抛异常,所有任务都被取消执行。
- Timer通过System.currentTimeMillis()方法获取时间,这时绝对时间,如果修改系统时间的话,会导致任务在错误的时间被执行;而ScheduledThreadPoolExecutor使用System.nanoTime(),是相对时间,不存在这个问题。
接下来关注几个修改配置的方法:
public void setContinueExistingPeriodicTasksAfterShutdownPolicy(boolean value) {
continueExistingPeriodicTasksAfterShutdown = value;
if (!value && isShutdown())
onShutdown();
}
设置在线程池关闭后,是否继续执行已有的周期性任务。为true时,通过调用shutdownNow可以终结这些任务。默认false。
public void setExecuteExistingDelayedTasksAfterShutdownPolicy(boolean value) {
executeExistingDelayedTasksAfterShutdown = value;
if (!value && isShutdown())
onShutdown();
}
设置在线程池关闭后,是否继续执行已有的延迟任务。为true时,通过调用shutdownNow可以终结这些任务。默认false。
public void setRemoveOnCancelPolicy(boolean value) {
removeOnCancel = value;
}
设置任务被取消后是否立即从队列中移除。默认false。