系統學習 Java 並發包(J.U.C)一段時間後,為了避免知識點碎片化,特整理此總結。文中若有疏漏,歡迎指正共同進步。轉載請註明出處:原文鏈接。
本文涵蓋 J.U.C 主要模塊:
JSR(Java Specification Requests)是向 JCP(Java Community Process)提交新增標準化技術規範的正式請求。每個 Java 版本更新都伴隨對應 JSR,如 Java 8 的 Lambda 表達式對應 JSR 335,新日期時間 API 對應 JSR 310。
JSR 166 專注於 Java 並發編程規範,在 JDK 中由 java.util.concurrent 包實現,於 JDK 5.0 引入。後續擴展包括:JDK 6 引入 Deques、Navigable collections(JSR 166x),JDK 7 引入 Fork/Join 框架(JSR 166y)。
J.U.C 是 java.util.concurrent 縮寫,參考自 EDU.oswego.cs.dl.util.concurrent,是 JSR 166 規範的標準實現。
JSR 166 及 J.U.C 核心作者為 Doug Lea 大神,其貢獻奠定了 Java 並發編程基石。

Executor 框架實現任務提交與執行解耦,核心接口與類關係如下:

頂層 Executor 接口僅定義 execute(Runnable command) 方法。Executors 工具類(類似 Collections)用於創建 ExecutorService、ScheduledExecutorService、ThreadFactory 及 Callable 對象。
Callable 或 Runnable)ExecutorService(如線程池)Future 對象get() 等待結果(可設置超時)ExecutorService executor = Executors.newCachedThreadPool(); Task task = new Task(); Future<Integer> result = executor.submit(task); result.get(); // 可傳入超時參數
Callable:有返回值,可拋出異常Runnable:無返回值,異常需內部處理通過 Executors 創建:
newFixedThreadPool:固定大小newCachedThreadPool:可緩存,適合短任務newSingleThreadExecutor:單線程串行newScheduledThreadPool:定時/周期執行定義任務集合 → 提交獲得 Future 集合 → 遍歷 get() 獲取結果
使用 ExecutorCompletionService 包裝線程池,調用 take() 從阻塞隊列獲取已完成任務的 Future
原理:CompletionService 內部維護 BlockingQueue,僅完成狀態的 Future 入隊,take() 可立即獲取最新完成任務。
AQS 是 J.U.C 實現鎖、同步器的基石,底層調用 LockSupport.park()/unpark() 實現線程阻塞喚醒。

state:volatile int 狀態變量,保證可見性final void lock() {
if (compareAndSetState(0, 1)) // CAS 嘗試獲取
setExclusiveOwnerThread(Thread.currentThread());
else
acquire(1); // 進入 AQS 獲取流程
}
acquire() → tryAcquire() 重試及重入判斷lock():阻塞獲取lockInterruptibly():可中斷獲取(synchronized 不支持)tryLock():非阻塞嘗試tryLock(time, unit):超時獲取unlock():釋放鎖newCondition():創建綁定條件變量支持公平/非公平模式:
注意:synchronized 也是可重入鎖,但缺乏可中斷、超時、公平性控制等高級特性。
規則:「讀讀共存、讀寫互斥、寫寫互斥」。讀多寫少場景下並發性能遠超排它鎖。
一個 Lock 可創建多個 Condition,實現精準喚醒:
await() ≈ Object.wait()signal() ≈ Object.notify()signalAll() ≈ Object.notifyAll()優勢:可為不同業務線程分配獨立 Condition,實現定向通知,避免驚群效應。
主線程等待 N 個事件完成:
countDown() 遞減await() 阻塞至計數歸零
特點:計數器不可重置,一次性使用。
多線程相互等待,齊聚屏障點後同時繼續:
await() 計數遞減並阻塞
特點:可重置循環使用,適合迭代計算。
控制同時訪問資源的線程數,實現資源池(連接池、線程池):
acquire():獲取許可,無則阻塞release():歸還許可喚醒等待者
兩線程在同步點交換數據:
exchange() 到達同步點
適用:雙緩衝、生產消費數據交換。
基於 sun.misc.Unsafe 實現,核心為 Compare-And-Swap:
public final boolean compareAndSet(int expect, int update) {
return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
}
現代 CPU 普遍支持 CAS 指令,實現無鎖線程安全。
AtomicInteger、AtomicLong、AtomicBooleanAtomicIntegerArray、AtomicReferenceArrayAtomicReference、AtomicStampedReference(解決 ABA 問題)AtomicIntegerFieldUpdater、AtomicLongFieldUpdateri++ 非原子操作(讀-改-寫三步),需用 atomicInteger.incrementAndGet() 替代。

| 類別 | 結構 | 邊界 | 特點 |
|---|---|---|---|
| ArrayBlockingQueue | 數組 | 有界 | 固定大小,公平/非公平可選 |
| LinkedBlockingQueue | 鏈表 | 有界(默認Integer.MAX) | 吞吐量高,靜態工廠常用 |
| PriorityBlockingQueue | 堆 | 無界 | 優先級排序 |
| DelayQueue | 堆 | 無界 | 延時獲取,定時任務基石 |
| SynchronousQueue | 無存儲 | 0 | 直接傳遞,Executors.cachedThreadPool 內部使用 |
| LinkedTransferQueue | 鏈表 | 無界 | transfer 方法語義更豐富 |
| LinkedBlockingDeque | 雙向鏈表 | 有界 | 雙端操作,工作竊取適用 |
ConcurrentModificationException(快速失效)
性能對比(數據來源參考文獻):

JDK 7 引入,基於「分治法」與「工作竊取算法」:
ForkJoinPool:執行引擎,空閒線程竊取他人任務ForkJoinTask:任務類型(RecursiveTask 有返回值、RecursiveAction 無返回值)
大任務可遞歸拆分為獨立子任務(如圖片處理、大數據排序、文件搜索)。
if (任務足夠小) {
直接執行;
} else {
拆分子任務;
invokeAll(子任務列表); // 並行執行並等待
合併結果;
}
// JDK 5 前 Thread.sleep(2400000); // 可讀性極差 // JDK 5 後 TimeUnit.SECONDS.sleep(4); TimeUnit.MINUTES.sleep(4); TimeUnit.HOURS.sleep(1); TimeUnit.DAYS.sleep(1);
TimeUnit.SECONDS.toMillis(44); // 返回 44000 TimeUnit.HOURS.toMinutes(2); // 返回 120