Executor
该类用来执行提交的任务,对任务提交和任务执行之间进行解耦,任务执行的细节包括线程的使用、调度等。通常使用Executor
而不是明确地创建线程。
Executor
的源码如下:
public interface Executor {
/**
* 在未来一定时间内执行给出的命令,这个命令可能在新线程、线程池的线程、调用线程执行,这取决于Executor的实现。
*/
void execute(Runnable command);
}
例如,相比创建线程,然后让他执行:
new Thread(new(RunnableTask())).start()
可以这样使用Executor
类:
Executor executor = ... //得到一个Executor对象
executor.execute(new RunnableTask1()); //将一个Runnable对象传入execute方法
executor.execute(new RunnableTask2());
...
Executor
并不严格要求任务执行是异步的。最简单的情况下,提交的任务可以在调用者的线程执行:
class DirectExecutor implements Executor {
public void execute(Runnable r) {
r.run();
}
}
更典型的情况下,任务在其他线程执行,而不是在调用者的线程:
class ThreadPerTaskExecutor implements Executor {
//为每个任务创建一个线程
public void execute(Runnable r) {
new Thread(r).start();
}
}
许多Executor
的实现类对任务何时执行、怎样执行实施一些限制。如下的Executor
将提交的任务序列化到另一个executor
,这是一个复合的executor
:
class SerialExecutor implements Executor {
final Queue<Runnable> tasks = new ArrayDeque<Runnable>();
final Executor executor;
Runnable active;
SerialExecutor(Executor executor) {
this.executor = executor;
}
public synchronized void execute(final Runnable r) {
tasks.offer(new Runnable() { //用一个Runnable封装参数给出的Runnable r,并放到tasks队列中
public void run() {
try {
r.run();
} finally {
scheduleNext(); //外层封装的Runnable在运行结束时调度下一个任务
}
}
});
if (active == null) {
scheduleNext();
}
}
protected synchronized void scheduleNext() {
if ((active = tasks.poll()) != null) { //如果还有任务,就对他进行调度
executor.execute(active);
}
}
}
ExecutorService
这个接口提供了终止线程和跟踪异步任务进度的方法。它继承了Executor
接口:
public interface ExecutorService extends Executor {
该接口包含的方法:
/**
* 启动有序关闭,在此过程中执行以前提交的任务,但不接受任何新任务。
* 此方法不会等待以前提交的任务执行完成。用awaitTermination来等待任务执行完成。
*/
void shutdown();
/**
* 停止所有正在执行的任务,停止处理正在等待的任务,并返回一个等待执行的任务列表。
*/
List<Runnable> shutdownNow();
/**
* 判断线程池是否已经关闭。
*/
boolean isShutdown();
/**
* 当线程池调用shutdown后,判断线程池的所有任务是否都已完成。
*/
boolean isTerminated();
/**
* 调用后将会shutdown线程池,然后阻塞直至所有任务完成/超时/当前线程被中断。
*/
boolean awaitTermination(long timeout, TimeUnit unit)
throws InterruptedException;
/**
* 提交一个具有返回值的任务执行。返回的Future对象代表将来计算完成得到的结果。
*/
<T> Future<T> submit(Callable<T> task);
/**
* 执行给出的任务,并返回Future对象的列表
*/
<T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks) throws InterruptedException;
/**
* 执行给出的任务,并返回第一个已完成执行的Future对象
*/
<T> T invokeAny(Collection<? extends Callable<T>> tasks)
throws InterruptedException, ExecutionException;
其中submit
方法既可以接受一个Runnable
也可以接受一个Callable
,并且返回一个代表计算结果的Future
;而继承自Executor
的execute
方法只能接受一个Runnable
,它没有返回值。
以上方法还有几种重载形式,在此不再赘述。
AbstractExecutorService
这个抽象类是ExecutorService
的默认实现。
public abstract class AbstractExecutorService implements ExecutorService {
/**
* 为给出的Runnable对象和默认返回值返回一个RunnableFuture对象
*/
protected <T> RunnableFuture<T> newTaskFor(Runnable runnable, T value) {
return new FutureTask<T>(runnable, value);
}
/**
* 为给出的Callable对象任务返回一个RunnableFuture对象
*/
protected <T> RunnableFuture<T> newTaskFor(Callable<T> callable) {
return new FutureTask<T>(callable);
}
/**
* 提交一个没有返回值任务,submit方法直接调用了execute方法执行任务
*/
public Future<?> submit(Runnable task) {
if (task == null) throw new NullPointerException();
RunnableFuture<Void> ftask = newTaskFor(task, null);
execute(ftask);
return ftask;
}
/**
* 提交一个Runnable对象描述的任务,并且带有返回值
*/
public <T> Future<T> submit(Runnable task, T result) {
if (task == null) throw new NullPointerException();
RunnableFuture<T> ftask = newTaskFor(task, result);
execute(ftask);
return ftask;
}
/**
* 提交一个callable对象描述的任务
*/
public <T> Future<T> submit(Callable<T> task) {
if (task == null) throw new NullPointerException();
RunnableFuture<T> ftask = newTaskFor(task);
execute(ftask);
return ftask;
}
/**
* 这是invokeAny的主要实现方法
*/
private <T> T doInvokeAny(Collection<? extends Callable<T>> tasks,
boolean timed, long nanos)
throws InterruptedException, ExecutionException, TimeoutException {
if (tasks == null)
throw new NullPointerException();
int ntasks = tasks.size();
if (ntasks == 0)
throw new IllegalArgumentException();
ArrayList<Future<T>> futures = new ArrayList<Future<T>>(ntasks);
//ExecutorCompletionService能够用提供的Executor执行任务,这个类将提交的任务在完成后放置到一个队列中,并使用take方法进行访问
ExecutorCompletionService<T> ecs =
new ExecutorCompletionService<T>(this);
// 为了提高效率,特别是在并行能力有限的executor中,在提交更多任务之前,检查先前提交的任务是否已经完成
try {
// 记录异常,如果获取结果失败,就抛出最近的一个异常
ExecutionException ee = null;
final long deadline = timed ? System.nanoTime() + nanos : 0L;
Iterator<? extends Callable<T>> it = tasks.iterator();
// 先开始第一个任务
futures.add(ecs.submit(it.next()));
--ntasks;
int active = 1;
for (;;) {
Future<T> f = ecs.poll();
if (f == null) { //队列为空
if (ntasks > 0) {
--ntasks;
futures.add(ecs.submit(it.next())); //继续提交任务
++active;
}
else if (active == 0) //没有活跃的线程了就退出循环
break;
else if (timed) { //如果任务计时,则如果在指定时间内仍poll出一个null,说明任务还没完成,抛出异常
f = ecs.poll(nanos, TimeUnit.NANOSECONDS);
if (f == null)
throw new TimeoutException();
nanos = deadline - System.nanoTime(); //剩余时间
}
else
f = ecs.take();
}
if (f != null) { //有新的任务完成了
--active;
try {
return f.get(); //从future对象获取返回值返回
} catch (ExecutionException eex) {
ee = eex;
} catch (RuntimeException rex) {
ee = new ExecutionException(rex);
}
}
}
if (ee == null)
ee = new ExecutionException();
throw ee;
} finally {
for (int i = 0, size = futures.size(); i < size; i++)
futures.get(i).cancel(true); //退出前取消任务
}
}
/**
* 执行给出的任务,并返回第一个已完成执行的Future对象
*/
public <T> T invokeAny(Collection<? extends Callable<T>> tasks)
throws InterruptedException, ExecutionException {
try {
return doInvokeAny(tasks, false, 0);
} catch (TimeoutException cannotHappen) {
assert false;
return null;
}
}
public <T> T invokeAny(Collection<? extends Callable<T>> tasks,
long timeout, TimeUnit unit)
throws InterruptedException, ExecutionException, TimeoutException {
return doInvokeAny(tasks, true, unit.toNanos(timeout));
}
public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks)
throws InterruptedException {
if (tasks == null)
throw new NullPointerException();
ArrayList<Future<T>> futures = new ArrayList<Future<T>>(tasks.size());
boolean done = false;
try {
for (Callable<T> t : tasks) {
RunnableFuture<T> f = newTaskFor(t);
futures.add(f);
execute(f);
}
for (int i = 0, size = futures.size(); i < size; i++) {
Future<T> f = futures.get(i);
if (!f.isDone()) { //如果当前任务还没完成就阻塞
try {
f.get(); //get方法能够使当前线程阻塞直到任务完成
} catch (CancellationException ignore) {
} catch (ExecutionException ignore) {
}
}
}
done = true;
return futures;
} finally {
if (!done) //如果没有完成全部任务,说明抛出了未捕获异常,取消所有任务
for (int i = 0, size = futures.size(); i < size; i++)
futures.get(i).cancel(true);
}
}
public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks,
long timeout, TimeUnit unit)
throws InterruptedException {
if (tasks == null)
throw new NullPointerException();
long nanos = unit.toNanos(timeout);
ArrayList<Future<T>> futures = new ArrayList<Future<T>>(tasks.size());
boolean done = false;
try {
for (Callable<T> t : tasks)
futures.add(newTaskFor(t));
final long deadline = System.nanoTime() + nanos;
final int size = futures.size();
// Interleave time checks and calls to execute in case
// executor doesn't have any/much parallelism.
for (int i = 0; i < size; i++) {
execute((Runnable)futures.get(i));
nanos = deadline - System.nanoTime();
if (nanos <= 0L)
return futures;
}
for (int i = 0; i < size; i++) {
Future<T> f = futures.get(i);
if (!f.isDone()) {
if (nanos <= 0L)
return futures;
try {
f.get(nanos, TimeUnit.NANOSECONDS); //限定执行时间,如果超时就抛出TimeoutException
} catch (CancellationException ignore) {
} catch (ExecutionException ignore) {
} catch (TimeoutException toe) {
return futures; //超时直接将futures容器返回
}
nanos = deadline - System.nanoTime(); //计算剩余时间
}
}
done = true;
return futures;
} finally {
if (!done)
for (int i = 0, size = futures.size(); i < size; i++)
futures.get(i).cancel(true);
}
}
}
使用Executor类的优点
如果不用Executor
类,任务的提交和执行策略耦合,如下:
class ThreadPerTaskWebServer {
public static void main(String[] args) throws IOException {
ServerSocket socker = new ServerSocket(80);
while(true) {
final Socket connection = socker.accept();
Runnable task = new Runnable() {
@Override
public void run() {
handleRequest(connection);
}
};
//为每个任务创建一个线程
new Thread(task).start();
}
}
private static void handleRequest(Socket connection) {
//...
}
}
在Java类库中,任务执行的主要抽象不是Thread
,而是Executor
。
以下例子用Executor
决定具体的执行策略:
class TaskExecutorWebServer {
private static final int NTHREADS = 100;
//通过选择具体的Executor决定执行策略
private static final Executor exec = Executors.newFixedThreadPool(NTHREADS);
public static void main(String[] args) throws IOException {
ServerSocket socker = new ServerSocket(80);
while(true) {
Socket conn = socker.accept();
Runnable task = new Runnable() {
@Override
public void run() {
handleRequest(conn);
}
};
exec.execute(task);
}
}
private static void handleRequest(Socket conn) {
//...
}
}
如果仍想为每个请求创建一个线程,也可以用Executor
实现,只需实现Executor
接口:
class ThreadPerTaskWebServer implements Executor {
@Override
public void execute(Runnable r) {
new Thread(r).start();
}
}
于是,当出现如下代码:
new Thread(runnable).start();
并且希望得到更灵活的执行策略时,应考虑使用Executor
代替Thread
。