Executor接口
在Java类库中,任务执行的主要抽象不是Thread,而是Executor,接口声明:
public interface Executor {
void execute(Runnable command);
}
虽然Executor是个简单的接口,但它却为灵活且强大的异步任务执行框架提供了基础,该框架能支持多种不同类型的任务执行策略。它提供了一种标准的方法将任务的提交过程与执行过程解耦开来,并用Runnable来表示任务。Executor还提供了对生命周期的支持,以及统计信息收集、应用程序管理机制和性能监控等机制。
Executor基于生产者-消费者模式,提交任务的操作相当于生产者,执行任务的线程则相当于消费者。如果要在程序中实现一个生产者-消费者的设计,那么最简单的方式通常就是使用Executor。
每当看到下面这种形式的代码时:
new Thread(runnable).start()
并且希望获得一种更灵活的执行策略时,请使用Executor来代替Thread。
Executor的生命周期
由于Executor以异步的方式来执行任务,因此在任何时刻,之前提交的任务的状态不是立即可见的。为了解决执行服务的生命问题,Executor扩展了ExecutorService接口,添加了一些用于生命周期管理的方法(同时还有一些用于任务提交的便利方法)。ExecutorService接口声明:
public interface ExecutorService extends Executor {
void shutdown();
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;
}
ExecutorService的生命周期有3种运行状态:运行、关闭和已终止。ExecutorService在初始创建时处于运行状态。shutdown方法将执行平缓的关闭过程:不再接受新的任务,同时等待已经提交的任务执行完成——包括那些还未开始的任务。shutdowNow方法将执行粗暴的关闭过程:它将尝试取消所有运行中的任务,并且不再启动队列中尚未开始执行的任务。
Executor的默认实现 —— AbstractExecutor
Executor,ExecutorService只是两个接口,抽象类AbstractExecutor实现了ExecutorService接口,基本实现了ExecutorService中声明的所有方法;
下面来看几个比较重要的方法的实现:
- newTaskFor()方法:
protected <T> RunnableFuture<T> newTaskFor(Callable<T> callable) {
return new FutureTask<T>(callable);
}
newTaskFor方法为callable任务返回了一个FutureTask对象。这个FutureTask对象运行时会调用底层的callable任务。 关于Callable、Future、及FutureTask相关内容可参看:Java并发
newTaskFor方法可由子类覆写。
- submit()方法:
public <T> Future<T> submit(Callable<T> task) {
if (task == null) throw new NullPointerException();
RunnableFuture<T> ftask = newTaskFor(task);
execute(ftask);
return ftask;
}
submit方法首先调用newTaskFor方法,返回一个RunnableFuture任务对象FutureTask,然后交给execute方法执行,上面说过FutureTask在执行时会调用传入的Callable任务,所以execute方法最终会执行传入的Callable任务。execute方法由继承AbstractExecutor的子类实现,最后将RunnableTask对象返回。