JDK源码分析-ScheduledExecutorService

概述

接口的继承结构如下:
JDK源码分析-ScheduledExecutorService
下面分析这几个接口的定义。

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 这三个接口,它们之间是继承关系,主要都是围绕“执行任务”这个核心来的:

  1. Executor 只有一个 execute 方法,只能执行 Runnable 任务,且无返回值;

  2. ExecutorService 增强了 Executor 的功能,主要包括可以提交 Callable 任务,且有返回值;

  3. ScheduledExecutorService 进一步增强了 ExecutorService 的功能,增加了延迟执行任务和周期性执行任务的功能。

JDK源码分析-ScheduledExecutorService

上一篇:线程池 掌握治理线程的法宝


下一篇:多线程JUC包之CountDownLatch