package java.util.concurrent; public class ExecutorCompletionService<V> implements CompletionService<V> { private final Executor executor; private final AbstractExecutorService aes; private final BlockingQueue<Future<V>> completionQueue; private class QueueingFuture extends FutureTask<Void> { QueueingFuture(RunnableFuture<V> task) { super(task, null); this.task = task; } protected void done() { completionQueue.add(task); } private final Future<V> task; } private RunnableFuture<V> newTaskFor(Callable<V> task) { if (aes == null) return new FutureTask<V>(task); else return aes.newTaskFor(task); } private RunnableFuture<V> newTaskFor(Runnable task, V result) { if (aes == null) return new FutureTask<V>(task, result); else return aes.newTaskFor(task, result); } public ExecutorCompletionService(Executor executor) { if (executor == null) throw new NullPointerException(); this.executor = executor; this.aes = (executor instanceof AbstractExecutorService) ? (AbstractExecutorService) executor : null; this.completionQueue = new LinkedBlockingQueue<Future<V>>(); } public ExecutorCompletionService(Executor executor, BlockingQueue<Future<V>> completionQueue) { if (executor == null || completionQueue == null) throw new NullPointerException(); this.executor = executor; this.aes = (executor instanceof AbstractExecutorService) ? (AbstractExecutorService) executor : null; this.completionQueue = completionQueue; } public Future<V> submit(Callable<V> task) { if (task == null) throw new NullPointerException(); RunnableFuture<V> f = newTaskFor(task); executor.execute(new QueueingFuture(f)); return f; } public Future<V> submit(Runnable task, V result) { if (task == null) throw new NullPointerException(); RunnableFuture<V> f = newTaskFor(task, result); executor.execute(new QueueingFuture(f)); return f; } public Future<V> take() throws InterruptedException { return completionQueue.take(); } public Future<V> poll() { return completionQueue.poll(); } public Future<V> poll(long timeout, TimeUnit unit) throws InterruptedException { return completionQueue.poll(timeout, unit); } }
全部已实现的接口:html
CompletionService<V> java
使用提供的 Executor
来执行任务的 CompletionService
。api
此类将安排那些完成时提交的任务,把它们放置在可以使用 take 访问的队列上。this
该类很是轻便,适合于在执行几组任务时临时使用。spa
用法示例。 假定您有针对某个问题的一组求解程序,每一个求解程序都能返回某种类型的 Result 值,而且您想同时运行它们,使用方法 use(Result r) 处理返回非 null 值的每一个求解程序的返回结果。能够这样编写程序:.net
void solve(Executor e, Collection<Callable<Result>> solvers)
throws InterruptedException, ExecutionException {
CompletionService<Result> ecs = new ExecutorCompletionService<Result>(e);
for (Callable<Result> s : solvers)
ecs.submit(s);
int n = solvers.size();
for (int i = 0; i < n; ++i) {
Result r = ecs.take().get();
if (r != null)
use(r);
}
}
假定您想使用任务集中的第一个非 null 结果,而忽略任何遇到异常的任务,而且在第一个任务就绪时取消其余全部任务:线程
void solve(Executor e, Collection<Callable<Result>> solvers)
throws InterruptedException {
CompletionService<Result> ecs = new ExecutorCompletionService<Result>(e);
int n = solvers.size();
List<Future<Result>> futures = new ArrayList<Future<Result>>(n);
Result result = null;
try {
for (Callable<Result> s : solvers)
futures.add(ecs.submit(s));
for (int i = 0; i < n; ++i) {
try {
Result r = ecs.take().get();
if (r != null) {
result = r;
break;
}
} catch(ExecutionException ignore) {}
}
}
finally {
for (Future<Result> f : futures)
f.cancel(true);
}
if (result != null)
use(result);
}
构造方法摘要code
ExecutorCompletionService(Executor executor) 使用为执行基本任务而提供的执行程序建立一个 ExecutorCompletionService,并将 LinkedBlockingQueue 做为完成队列。 |
ExecutorCompletionService(Executor executor, BlockingQueue<Future<V>> completionQueue) 使用为执行基本任务而提供的执行程序建立一个 ExecutorCompletionService,并将所提供的队列做为其完成队列。 |
方法摘要htm
Future<V> |
poll() 获取并移除表示下一个已完成任务的 Future,若是不存在这样的任务,则返回 null。 |
Future<V> |
poll(long timeout, TimeUnit unit) 获取并移除表示下一个已完成任务的 Future,若是目前不存在这样的任务,则将等待指定的时间(若是有必要)。 |
Future<V> |
submit(Callable<V> task) 提交要执行的值返回任务,并返回表示挂起的任务结果的 Future。 |
Future<V> |
submit(Runnable task, V result) 提交要执行的 Runnable 任务,并返回一个表示任务完成的 Future,能够提取或轮询此任务。 |
Future<V> |
take() 获取并移除表示下一个已完成任务的 Future,若是目前不存在这样的任务,则等待。 |
从类 java.lang.Object 继承的方法blog
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
public ExecutorCompletionService(Executor executor)
使用为执行基本任务而提供的执行程序建立一个 ExecutorCompletionService,并将 LinkedBlockingQueue
做为完成队列。
参数:
executor
- 要使用的执行程序
抛出:
NullPointerException
- 若是执行程序为 null
public ExecutorCompletionService(Executor executor, BlockingQueue<Future<V>> completionQueue)
使用为执行基本任务而提供的执行程序建立一个 ExecutorCompletionService,并将所提供的队列做为其完成队列。
参数:
executor
- 要使用的执行程序
completionQueue
- 用做完成队列的队列,一般是专供此服务使用的队列
抛出:
NullPointerException
- 若是执行程序或 completionQueue 为 null
public Future<V> submit(Callable<V> task)
从接口 CompletionService
复制的描述
提交要执行的值返回任务,并返回表示挂起的任务结果的 Future。在完成时,可能会提取或轮询此任务。
指定者:
接口 CompletionService<V>
中的 submit
参数:
task
- 要提交的任务
返回:
一个表示挂起的任务完成的 Future
public Future<V> submit(Runnable task, V result)
从接口 CompletionService
复制的描述
提交要执行的 Runnable 任务,并返回一个表示任务完成的 Future,能够提取或轮询此任务。
指定者:
接口 CompletionService<V>
中的 submit
参数:
task
- 要提交的任务
result
- 要返回的已成功完成任务的结果
返回:
一个表示挂起的任务完成的 Future,其 get() 方法将返回完成时给出的结果值
public Future<V> take() throws InterruptedException
从接口 CompletionService
复制的描述
获取并移除表示下一个已完成任务的 Future,若是目前不存在这样的任务,则等待。
指定者:
接口 CompletionService<V>
中的 take
返回:
表示下一个已完成任务的 Future
抛出:
InterruptedException
- 若是在等待时被中断
public Future<V> poll()
从接口 CompletionService
复制的描述
获取并移除表示下一个已完成任务的 Future,若是不存在这样的任务,则返回 null。
指定者:
接口 CompletionService<V>
中的 poll
返回:
表示下一个已完成任务的 Future;若是不存在这样的任务,则返回 null
public Future<V> poll(long timeout, TimeUnit unit) throws InterruptedException
从接口 CompletionService
复制的描述
获取并移除表示下一个已完成任务的 Future,若是目前不存在这样的任务,则将等待指定的时间(若是有必要)。
指定者:
接口 CompletionService<V>
中的 poll
参数:
timeout
- 放弃以前须要等待的时间长度,以 unit 为时间单位
unit
- 肯定如何解释 timeout 参数的 TimeUnit
返回:
表示下一个已完成任务的 Future;若是等待了指定时间仍然不存在这样的任务,则返回 null
抛出:
InterruptedException
- 若是在等待时被中断