它跟普通的Executor + Callable + Future 没什么本质区别。只不过当有多个任务需要提交时,自己手动维护一堆Future、并依次地调用future.get() 会很繁琐。 CompletionService使这个变得简单很多。
package player.kent.chen.learn.completionservice; import java.io.File; import java.util.concurrent.Callable; import java.util.concurrent.CompletionService; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorCompletionService; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; import org.apache.commons.io.FileUtils; public class HelloCompletionService { public static void main(String[] args) throws InterruptedException { //生成CompletionService实例 ExecutorService executor = Executors.newFixedThreadPool(2); CompletionService<String> completionService = new ExecutorCompletionService<String>( executor); //定义任务并置入CompletionService任务池 for (int i = 0; i < 4; i++) { final String fn = String.valueOf(i) + ".txt"; Callable<String> task = new Callable<String>() { public String call() throws Exception { return FileUtils.readFileToString(new File("/home/kent/temp/" + fn)); } }; completionService.submit(task); } for (int i = 0; i < 4; i++) { Future<String> future = null; try { //至少有一个任务完成了,take()才能拿到东西; 所以这里的future其实是done==true的future //这也正是CompletionService的作用:任务一旦完成,就可以被取到 future = completionService.take(); String text = future.get(); System.out.println(text); } catch (InterruptedException e) { Thread.currentThread().interrupt(); future.cancel(true); return; } catch (ExecutionException e) { e.printStackTrace(); //真正的应用中应该注意一下此处的处理 } } executor.shutdown(); executor.awaitTermination(1000l, TimeUnit.SECONDS); } }