並發編程是利用多核 CPU 提升吞吐量的關鍵。本文系統梳理:線程創建三種方式、volatile 可見性原理、synchronized 鎖優化演進、線程池 7 大參數與 4 種拒絕策略、任務隊列選型指南,構建並發知識骨架。
| 方式 | 關鍵點 | 優缺點 |
|---|---|---|
| 繼承 Thread | 重寫 run() | 簡單,但單繼承限制,邏輯與線程控制耦合 |
| 實現 Runnable | 實現 run(),傳入 Thread 構造器 | 支援多實現、邏輯解耦、可用線程池,**推薦** |
| 實現 Callable + FutureTask | call() 有返回值,Future.get() 阻塞獲取 | 需獲取結果時使用,配合線程池 submit() |
// Callable 範例 ExecutorService exec = Executors.newSingleThreadExecutor(); Future<String> fut = exec.submit(() -> "hello"); System.out.println(fut.get()); // 阻塞等待結果
lock 前綴指令 → 緩存行寫回主存 + 總線嗅探失效其他 CPU 緩存thisClass對象括號內對象對象頭 Mark Word 存儲鎖狀態:
無鎖(01) → 偏向鎖(01) → 輕量級鎖(00) → 重量級鎖(10) → GC標記(11)
public ThreadPoolExecutor(
int corePoolSize, // 核心線程數 (常駐)
int maximumPoolSize, // 最大線程數 (峰值)
long keepAliveTime, // 非核心線程閒置存活時間
TimeUnit unit, // 時間單位
BlockingQueue<Runnable> workQueue, // 任務隊列
ThreadFactory threadFactory, // 線程工廠 (命名、優先級、守護)
RejectedExecutionHandler handler // 拒絕策略
)
LinkedBlockingQueueSynchronousQueue (直接提交)| 策略 | 行為 | 適用場景 |
|---|---|---|
| AbortPolicy (默認) | 拋 RejectedExecutionException | 關鍵業務,需立即感知 |
| CallerRunsPolicy | 調用者線程執行任務 | 緩衝峰值,不丟任務,不拋異常 |
| DiscardPolicy | 靜默丟棄 | 非核心日誌、監控數據 |
| DiscardOldestPolicy | 丟棄隊列頭任務,重試提交 | 優先處理新請求的場景 |
| 隊列 | 特性 | 適用池 |
|---|---|---|
| ArrayBlockingQueue | 有界數組、FIFO | 固定大小池,需有界控制 |
| LinkedBlockingQueue | 無界鏈表、FIFO、吞吐高 | FixedThreadPool (默認)、單一池 |
| SynchronousQueue | 無容量、直接移交 | CachedThreadPool (默認)、高併發短任務 |
| PriorityBlockingQueue | 優先級排序 | 定時/優先任務 |
提交任務
│
├─ 線程數 < corePoolSize → 創建核心線程執行
│
├─ 線程數 ≥ corePoolSize → 入隊列
│ ├─ 入隊成功 → 等待執行
│ └─ 入隊失敗 (有界隊列滿)
│ ├─ 線程數 < maximumPoolSize → 創建非核心線程執行
│ └─ 線程數 ≥ maximumPoolSize → 執行拒絕策略
│
└─ 非核心線程閒置 > keepAliveTime → 回收
| 方法 | 底層參數 | 風險 |
|---|---|---|
| newFixedThreadPool | core=max=n, LinkedBlockingQueue | 隊列無界 → OOM |
| newCachedThreadPool | core=0, max=Integer.MAX, SynchronousQueue | 線程無界 → OOM |
| newSingleThreadExecutor | core=max=1, LinkedBlockingQueue | 隊列無界 → OOM |
| newScheduledThreadPool | core=n, max=Integer.MAX, DelayedWorkQueue | 非核心線程無界 |
阿里巴巴開發手冊強制:禁用 Executors 默認工廠,必須自定義 ThreadPoolExecutor 明確有界隊列與拒絕策略,防止生產 OOM。
new ThreadFactoryBuilder().setNameFormat("order-process-%d").build() (Guava),日誌排查秒定位shutdown() → awaitTermination() → shutdownNow(),配合 Spring @PreDestroy核心心法:並發無銀彈,「可見性、原子性、有序性」三性權衡;線程池參數無標準答案,唯有壓測、監控、迭代。先跑通單機並發,再考慮分佈式鎖、MQ 解耦。