主線程提交多個異步任務,希望 「有任務完成就處理結果,並按完成順序逐個處理」。ExecutorService.invokeAll 需等待所有完成,不符合需求。
public interface CompletionService<V> {
Future<V> submit(Callable<V> task);
Future<V> submit(Runnable task, V result);
Future<V> take() throws InterruptedException; // 阻塞等待下一個完成
Future<V> poll(); // 非阻塞,無完成返回 null
Future<V> poll(long timeout, TimeUnit unit); // 限時等待
}
Executor 執行任務、BlockingQueue<Future<V>> 存放完成結果QueueingFuture (繼承 FutureTask)done() → 將 Future 入隊take()/poll() 直接從隊列取出// 核心源碼邏輯
public Future<V> submit(Callable<V> task) {
RunnableFuture<V> f = newTaskFor(task);
executor.execute(new QueueingFuture(f)); // 包裝層
return f;
}
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;
}
public static void parse(List<String> urls) throws InterruptedException {
ExecutorService executor = Executors.newFixedThreadPool(10);
CompletionService<String> cs = new ExecutorCompletionService<>(executor);
for (String url : urls) cs.submit(new UrlTitleParser(url));
for (int i = 0; i < urls.size(); i++) {
Future<String> result = cs.take(); // 阻塞直到有結果
try { System.out.println(result.get()); }
catch (ExecutionException e) { e.printStackTrace(); }
}
executor.shutdown();
}
public static String search(List<String> engines, String keyword)
throws InterruptedException {
ExecutorService executor = Executors.newFixedThreadPool(10);
CompletionService<String> cs = new ExecutorCompletionService<>(executor);
List<Future<String>> futures = new ArrayList<>();
String result = null;
try {
for (String e : engines) futures.add(cs.submit(new SearchTask(e, keyword)));
for (int i = 0; i < engines.size(); i++) {
try {
result = cs.take().get();
if (result != null) break; // 獲得第一個有效結果
} catch (ExecutionException ignore) { /* 繼續等待下一個 */ }
}
} finally {
for (Future<String> f : futures) f.cancel(true); // 取消其餘任務
executor.shutdown();
}
return result;
}
invokeAny、超時控制、部分失敗容忍等進階模式LinkedBlockingQueue,可自定義有界隊列防止 OOM下一節將探討定時任務調度 (ScheduledExecutorService)。