概述
接口的继承结构如下:
下面分析这几个接口的定义。
Executor
从名字来看,Executor 可译为“执行器”,它的作用就是执行任务。该接口只有一个 execute 方法:
public interface Executor {
// 执行给定的任务(Runnable)
void execute(Runnable command);
}
该方法的作用就是(在将来的某个时间)执行给定的命令,即实现了 Runnable 接口的对象。该命令可能在一个新的线程中执行,也可能在调用它的线程中执行。它的用法示例代码如下:
Executor executor = ...;
executor.execute(new RunnableTask1());
executor.execute(new RunnableTask2());
PS: 前文分析的线程池类「JDK源码分析-ThreadPoolExecutor」就是该接口的一个实现类。
ExecutorService
ExecutorService 可理解为“执行器服务”,它继承自 Executor 接口,是对 Executor 的扩展,定义如下:
public interface ExecutorService extends Executor {
// 关闭执行器服务。在此过程中之前提交的任务会执行,但不接收新的任务。若已关闭则无效。
void shutdown();
// 尝试停止所有正在执行的任务,并返回等待执行的任务列表
List<Runnable> shutdownNow();
// 是否已关闭
boolean isShutdown();
// 是否已终止
boolean isTerminated();
// 阻塞,直到所有任务都在 shutdown 请求之后执行完毕,或者超时发生,或者当前线程被中断(以先发生的情况为准)
boolean awaitTermination(long timeout, TimeUnit unit)
throws InterruptedException;
// 提交一个 Callable 任务,有返回值
<T> Future<T> submit(Callable<T> task);
// 提交一个 Runnable 任务,有返回值(执行成功后返回 result 值)
<T> Future<T> submit(Runnable task, T result);
// 提交一个 Runnable 任务,有返回值(执行成功后返回 null)
Future<?> submit(Runnable task);
// 执行提交的 Callable 任务列表,并返回对应的 Future 结果(即批量执行任务)
<T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks)
throws InterruptedException;
// 与上述方法类似,多了超时等待。若任务超时则完不成
<T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks,
long timeout, TimeUnit unit) throws InterruptedException;
// 执行提交的 Callable 任务列表,返回已成功执行的任务的结果(无异常),若有的话。
<T> T invokeAny(Collection<? extends Callable<T>> tasks)
throws InterruptedException, ExecutionException;
// 与上述方法类似,多了超时等待
<T> T invokeAny(Collection<? extends Callable<T>> tasks,
long timeout, TimeUnit unit)
throws InterruptedException, ExecutionException, TimeoutException;
}
该接口与 Executor 相比,主要增加了有返回值的提交任务的方法。
PS: 可参考前文线程池 ThreadPoolExecutor 的相关分析;有关 Future 接口,前面「JDK源码分析-FutureTask」也已分析,这里不再赘述。
ScheduledExecutorService
ScheduledThreadPoolExecutor 接口继承自 ExecutorService 接口,该接口定义了延迟执行的方法和周期性执行的方法,如下:
public interface ScheduledExecutorService extends ExecutorService {
// 创建一次性操作(Runnable),该操作会在指定的延迟之后执行(其实就是创建了一个定时任务)
public ScheduledFuture<?> schedule(Runnable command,
long delay, TimeUnit unit);
// 与上述方法类型,参数类型不同(Callable)
public <V> ScheduledFuture<V> schedule(Callable<V> callable,
long delay, TimeUnit unit);
/*
* 创建并执行一个周期性的任务
* 执行时间分别为 initialDelay, initialDelay + period, initialDelay + 2*period, 以此类推
* 若有异常则停止后续的执行;若任务执行时间超过其周期,则后续执行会延迟开始
*/
public ScheduledFuture<?> scheduleAtFixedRate(Runnable command,
long initialDelay,
long period,
TimeUnit unit);
/*
* 创建并执行一个周期性的任务
* 该操作在给定的初始延迟之后首先启用,然后在一次执行结束和下一次执行开始之间使用给定的延迟。
* 该方法与上述有些易混淆,不同的地方在于:
* 上述方法是以每次开始执行的时间来计算;
* 而本方法是以每次执行结束的时间和下次开始执行的时间计算
*/
public ScheduledFuture<?> scheduleWithFixedDelay(Runnable command,
long initialDelay,
long delay,
TimeUnit unit);
}
ScheduledExecutorService 可以做一些延迟执行的任务,或者周期性执行的任务,它在 JDK 中有一个实现类 ScheduledThreadPoolExecutor,后文再进行分析。
小结
本文主要分析了 Executor、ExecutorService 和 ScheduledExecutorService 这三个接口,它们之间是继承关系,主要都是围绕“执行任务”这个核心来的:
-
Executor 只有一个 execute 方法,只能执行 Runnable 任务,且无返回值;
-
ExecutorService 增强了 Executor 的功能,主要包括可以提交 Callable 任务,且有返回值;
- ScheduledExecutorService 进一步增强了 ExecutorService 的功能,增加了延迟执行任务和周期性执行任务的功能。