package java.util.concurrent;

public class ExecutorCompletionService<V> implements CompletionService<V> {
//用来执行具体任务
private final Executor executor;
//用来封装Callable或Runnable对象
private final AbstractExecutorService aes;
//队列,用来存放已完成的任务
private final BlockingQueue<Future<V>> completionQueue;


//继承FutureTask,在发生done时把自己加入队列
//done方法不管是任务正常完成,还是取消,或者异常都会调用
private class QueueingFuture extends FutureTask<Void> {
QueueingFuture(RunnableFuture<V> task) {
super(task, null);
this.task = task;
}
//重写done方法,在任务完成后加入到队列
protected void done() { completionQueue.add(task); }
private final Future<V> task;
}

//包装Callable
private RunnableFuture<V> newTaskFor(Callable<V> task) {
if (aes == null)
return new FutureTask<V>(task);
else
return aes.newTaskFor(task);
}

//包装Runnable
private RunnableFuture<V> newTaskFor(Runnable task, V result) {
if (aes == null)
return new FutureTask<V>(task, result);
else
return aes.newTaskFor(task, result);
}

//构造参数传入Executor
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>>();
}

//构造参数传入Executor和队列
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);
//提交一个任务,创建QueueingFuture进行封装,在任务状态切换后回调done方法,把自己加入队列
executor.execute(new QueueingFuture(f));
return f;
}

//提交一个任务,创建QueueingFuture进行封装,在任务状态切换后回调done方法,把自己加入队列
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;
}

//获取并移除表示下一个已完成任务的 Future,如果目前不存在这样的任务,则等待.
public Future<V> take() throws InterruptedException {
return completionQueue.take();
}

//获取已完成的任务并移除,如果不存在则返回null.
public Future<V> poll() {
return completionQueue.poll();
}

//获取已完成的任务并移除,如果不存在则等待,超时后返回null
public Future<V> poll(long timeout, TimeUnit unit)
throws InterruptedException {
return completionQueue.poll(timeout, unit);
}

}


等待所有任务完成的例子:

package com.ht.web.nio;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorCompletionService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

public class Demo {

public static void main(String[] args) throws InterruptedException, ExecutionException {
ExecutorCompletionService<Integer> completionService = new ExecutorCompletionService<>(Executors.newFixedThreadPool(10));

List<Callable<Integer>> list = new ArrayList<>();
list.add(() -> {Thread.sleep(3000); System.out.println(Thread.currentThread().getName() + "--> 1"); return 1;});
list.add(() -> {Thread.sleep(3000); System.out.println(Thread.currentThread().getName() + "--> 2"); return 2;});
list.add(() -> {Thread.sleep(3000); System.out.println(Thread.currentThread().getName() + "--> 3"); return 3;});
list.add(() -> {Thread.sleep(3000); System.out.println(Thread.currentThread().getName() + "--> 4"); return 4;});

for (Callable<Integer> callable : list) {
completionService.submit(callable);
}

for (int i = 0; i < list.size(); i++) {
Future<Integer> future = completionService.take();
System.out.println(future.isDone() + " + " + future.get());
}
}

}

只要有一个任务完成即可,结束其它任务:

package com.ht.web.nio;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorCompletionService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

public class Demo {

public static void main(String[] args) throws InterruptedException, ExecutionException {
ExecutorCompletionService<Integer> completionService = new ExecutorCompletionService<>(Executors.newFixedThreadPool(10));

List<Callable<Integer>> list = new ArrayList<>();
list.add(() -> {Thread.sleep(3000); System.out.println(Thread.currentThread().getName() + "--> 1"); return 1;});
list.add(() -> {Thread.sleep(3000); System.out.println(Thread.currentThread().getName() + "--> 2"); return 2;});
list.add(() -> {Thread.sleep(3000); System.out.println(Thread.currentThread().getName() + "--> 3"); return 3;});
list.add(() -> {Thread.sleep(3000); System.out.println(Thread.currentThread().getName() + "--> 4"); return 4;});


List<Future<Integer>> futures = new ArrayList<Future<Integer>>();

for (Callable<Integer> callable : list) {
futures.add(completionService.submit(callable));
}

Integer result = null;

try {
for (int i = 0; i < list.size(); i++) {
Future<Integer> future = completionService.take();
if(future.get() != null) {
result = future.get();
break;
}
}
} finally {
for (int i = 0; i < futures.size(); i++) {
futures.get(i).cancel(true);
}
}

if(result != null) {
System.out.println(result);
}
}

}