J2SE 5.0 引入 java.util.concurrent 套件,提供高層併發建構元件,解決傳統多執行緒程式設計「難寫、難除錯、難維護」的痛點。本文系統介紹 Executor 框架、排程服務、Future/Callable、ThreadPoolExecutor、併發集合、同步器六大核心組件。
// 介面定義
public interface Executor {
void execute(Runnable command);
}
// 同步執行實作
class MySynExecutor implements Executor {
public void execute(Runnable r) { r.run(); }
}
// 非同步執行實作(每任務一執行緒)
class MyASynExecutor implements Executor {
public void execute(Runnable r) { new Thread(r).start(); }
}
程式碼只需依賴 Executor 介面,具體執行策略(同步/非同步/線程池/排程)可隨時替換。
shutdown():停止接受新任務,處理完佇列任務shutdownNow():嘗試中斷執行中任務,返回未處理任務列表awaitTermination():等待終止submit(Runnable/Callable):提交任務並回傳 FutureScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
Runnable beeper = () -> System.out.println("beep");
// 1 秒後開始,每 5 秒執行一次
ScheduledFuture> handle = scheduler.scheduleAtFixedRate(beeper, 1, 5, TimeUnit.SECONDS);
// 取消:handle.cancel(true);
適用:定期清理暫存檔、心跳檢測、資料同步等。
舊版 run() 回傳 void,取值極麻煩。Callable 回傳 V,配合 Future:
Future future = executor.submit(() -> {
// 耗時運算...
return "result";
});
// 主執行緒可輪詢
while (!future.isDone()) { Thread.sleep(500); }
String result = future.get(); // 阻塞直到完成
FutureTask 實作 RunnableFuture,可直接提交給 Executor。
| 參數 | 說明 |
|---|---|
| corePoolSize | 核心線程數(常駐) |
| maximumPoolSize | 最大線程數 |
| keepAliveTime | 非核心線程閒置存活時間 |
| workQueue | 任務佇列(有界/無界) |
| threadFactory | 線程建立工廠(命名、優先權、Daemon) |
| RejectedExecutionHandler | 拒絕策略(Abort/Discard/CallerRuns) |
排隊規則:
Hook 方法:beforeExecute()/afterExecute()(需繼承覆寫),適合監控、日誌、計時。
| 類別 | 特性 | 適用場景 |
|---|---|---|
| ConcurrentHashMap | 分段鎖,高併發讀寫 | 快取、計數器、註冊表 |
| CopyOnWriteArrayList | 寫入複製底層陣列 | 讀多寫少、遍歷無需鎖 |
| CopyOnWriteArraySet | 同上,Set 語意 | 事件監聽器清單等 |
迭代器提供快照視圖:迭代過程不受並發修改影響,不拋 ConcurrentModificationException。
Semaphore:信號量,控制同時存取數CountDownLatch:倒數閂,等待 N 個事件完成CyclicBarrier:循環柵欄,固定執行緒集合同步點Exchanger:雙方交換資料需配合併發理論背景使用,文末附參考資源。
有了 java.util.concurrent,不再需要手寫 wait/notify、線程池、佇列。標準化、高效能、經實戰驗證的組件,讓多執行緒開發從「挑戰」變成「工程」。