Executor、ExecutorService、Executors详解

130 阅读2分钟

Executor

Executor 是一个抽象层面的 根接口,下面是它的源代码:

public interface Executor {
    /**
     * Executes the given command at some time in the future.  The command
     * may execute in a new thread, in a pooled thread, or in the calling
     * thread, at the discretion of the {@code Executor} implementation.
     *
     * @param command the runnable task
     * @throws RejectedExecutionException if this task cannot be
     * accepted for execution
     * @throws NullPointerException if command is null
     */
    void execute(Runnable command);
}

可以看到,该接口中就只有一个execute()方法

那 Thread and Executor 的区别在哪,为什么已经有了 Thread 又要弄个 Executor 接口出来,在 Java 中,Thread 和 Executor(及其扩展接口/实现类)是两种不同的任务执行模型,不同于 Thread 类将任务和执行耦合在一起, Executor 将 任务本身和执行任务分离

共同点:两者最终都通过RunnableCallable定义任务逻辑

协作场景ThreadPoolExecutorExecutor的实现类)内部实际使用Thread来执行任务

graph LR
    Thread(Thread) -->|手动管理| Runnable/Callable
    Executor(Executor) -->|统一调度| Runnable/Callable
    Executor --> ExecutorService --> ThreadPoolExecutor

ExecutorService

ExecutorService 接口,是继承了 Executor 接口并对其进行了扩展,例如提供了返回 Future 对象,终止,关闭线程池等方法

public interface ExecutorService extends Executor, AutoCloseable {

    void shutdown();

    List<Runnable> shutdownNow();

    boolean isShutdown();

    boolean isTerminated();

    boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException;

    <T> Future<T> submit(Callable<T> task);

    <T> Future<T> submit(Runnable task, T result);

    Future<?> submit(Runnable task);

    <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;

    <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;

    @Override
    default void close() {
        boolean terminated = isTerminated();
        if (!terminated) {
            shutdown();
            boolean interrupted = false;
            while (!terminated) {
                try {
                    terminated = awaitTermination(1L, TimeUnit.DAYS);
                } catch (InterruptedException e) {
                    if (!interrupted) {
                        shutdownNow();
                        interrupted = true;
                    }
                }
            }
            if (interrupted) {
                Thread.currentThread().interrupt();
            }
        }
    }
}

Future 接口

Future 提供了异步执行,无需等待任务执行完成,只要提交需要执行的任务,然后在需要时检查 Future 是否已经有了结果,如果任务已经执行完成,就可以通过 Future.get() 方法获得执行结果,但需要注意的是,Future.get() 方法是一个阻塞的方法,如果调用时任务还没有执行完,会保持等待直到任务执行结束

Executors

Executors 类似于 Collections 、Arrays 等 ,是一个工具类,提供了一系列静态方法来创建不同类型的线程池,但是一般都会采用自定义线程池的方式来实现,因为Executors虽然方便,但是不利于控制线程池的运行规则,可能会导致资源耗尽的风险

// 固定大小线程池
ExecutorService fixedPool = Executors.newFixedThreadPool(10);

// 缓存线程池
ExecutorService cachedPool = Executors.newCachedThreadPool();

// 单线程线程池
ExecutorService singlePool = Executors.newSingleThreadExecutor();

// 定时任务线程池
ScheduledExecutorService scheduledPool = Executors.newScheduledThreadPool(5);

线程池详解