前言
多執行緒是 Java 後端開發的核心童子功,也是面試高頻考點。本文精選 40 個涵蓋 基礎 API、鎖機制、併發容器、線程池、JMM、鎖優化、分佈式鎖 等維度的知識點,每題附帶核心結論與原理分析,助你系統化構建知識體系。
一、基礎篇 (1-10)
- Thread vs Runnable vs Callable:Runnable/Callable 解耦任務與執行,Callable 有返回值並拋異常,配合 FutureTask 使用。
- start() vs run():start() 啟動新執行緒,run() 只是普通方法調用,仍在當前執行緒執行。
- sleep() vs wait():sleep() 不釋放鎖,wait() 釋放鎖並進入等待集,需配合 synchronized/notify。
- yield():禮讓 CPU,不保證調度,不釋放鎖。
- join():等待目標執行緒終止,底層用 wait() 實現。
- 守護執行緒:setDaemon(true),JVM 只有守護執行緒時會退出 (如 GC)。
- 中斷機制:interrupt() 設標誌位,isInterrupted() 檢查,InterruptedException 會清除標誌,需重新設定。
- volatile 關鍵字:保證可見性、禁止指令重排,不保證原子性 (long/double 除外)。
- synchronized 鎖升級:偏向鎖 → 輕量級鎖 (CAS) → 重量級鎖 (OS Mutex),JDK 1.6+ 大幅優化。
- 死鎖條件與預防:互斥、持有並等待、不可搶佔、循環等待。預防:固定獲取順序、tryLock 超時、避免嵌套鎖。
二、鎖與同步器篇 (11-20)
- ReentrantLock vs synchronized:前者支援公平鎖、可中斷、超時獲取、多條件變數 (Condition)、非塊結構鎖。
- AQS (AbstractQueuedSynchronizer):狀態 + CLH 隊列,模板方法模式。獨占/共享模式。ReentrantLock、Semaphore、CountDownLatch 皆基於此。
- Condition vs Object.wait/notify:Condition 綁定 Lock,支援多等待隊列、精確喚醒、可中斷等待。
- ReadWriteLock (ReentrantReadWriteLock):讀讀共存、讀寫互斥、寫寫互斥。適合讀多寫少場景。注意鍵降級 (寫→讀) 支援,升級不支援。
- StampedLock:JDK 8 引入,樂觀讀鎖 (無鎖讀,驗證戳版),性能更優,但不支援 Condition、不可重入。
- Semaphore:信號量控制並發訪問數 (資源池、限流)。acquire/release。
- CountDownLatch vs CyclicBarrier:前者一次性倒數 (主線程等待多子任務),後者可循環重置 (多線程相互等待集合點)。
- Phaser:JDK 7 更強大的柵欄,支援動態註冊/取消註冊、階段推進。
- Exchanger:雙方交換數據 (雙緩衝、生產消費配對)。
- LockSupport park/unpark:線程阻塞/喚醒原語,不需鎖對象,AQS 底層依賴它。
三、併發容器與工具篇 (21-30)
- ConcurrentHashMap (JDK 8):Node[] + synchronized (頭節點) + CAS + 長鏈表樹化 (紅黑樹)。擴容多線程協助。size() 用 LongAdder 累加。
- CopyOnWriteArrayList/Set:寫時複製底層數組,讀無鎖。適合讀極多、寫極少、容忍短暫不一致場景 (事件監聽器)。
- BlockingQueue 族系:ArrayBlockingQueue (有界)、LinkedBlockingQueue (無界/有界)、SynchronousQueue (直接遞交)、DelayQueue (延遲)、PriorityBlockingQueue (優先級)。
- ThreadLocal 原理:ThreadLocalMap (Entry 弱引用 Key),防記憶體洩漏需手動 remove()。InheritableThreadLocal 父子傳遞。
- LongAdder / DoubleAdder:熱點計數器,分段 CAS (Cell[]),最終求和,高併發優於 AtomicLong。
- CompletableFuture:非阻塞鏈式編程,supplyAsync/thenApply/thenCompose/allOf/anyOf,異常處理 exceptionally/handle。
- Parallel Stream 陷阱:共用 ForkJoinPool.commonPool,CPU 密集任務會互相影響,建議自定義線程池。
- ConcurrentLinkedQueue:無鎖隊列 (CAS),適合高併發生產消費,無阻塞等待。
- EnumMap / EnumSet:鍵為 Enum 時極致性能 (位向量/數組索引)。
- WeakHashMap:Key 弱引用,GC 時自動移除,適合緩存、元數據映射。
四、線程池與進階篇 (31-40)
- ThreadPoolExecutor 7 大參數:core/maximumPoolSize、keepAliveTime、workQueue、threadFactory、handler (拒絕策略)。
- 四種拒絕策略:AbortPolicy (拋異常)、CallerRunsPolicy (調用者執行)、DiscardPolicy (丟棄)、DiscardOldestPolicy (丟棄最老)。
- Executors 預設工廠缺陷:FixedThreadPool (OOM 風險、無界隊列)、CachedThreadPool (無限創建線程)、SingleThreadExecutor (隊列無界)。生產環境禁用,自定義構建。
- 線程池監控指標:activeCount、queueSize、completedTaskCount、rejectCount、keepAliveTime 觸發縮容。
- 優雅關閉:shutdown() 不接受新任務處理完隊列 → shutdownNow() 嘗試中斷執行中任務 → awaitTermination() 等待。
- JMM (Java Memory Model) - Happens-Before:程序順序、鎖規則、volatile 規則、線程啟動/終止、傳遞性、中斷規則。
- 指令重排與內存屏障:編譯器/CPU 重排。volatile 寫/讀插入 StoreLoad/LoadLoad 屏障。final 域寫入屏障。
- 偽共享:多線程修改同一緩存行不同變量導致緩存行 ping-pong。@Contended (JDK 9+) 或填充長數組避免。
- 分佈式鎖 (Redis/Redisson):SET NX PX + Lua 腳本原子性、看門狗自動續期、可重入、紅鎖 (Redlock) 多實例高可用。
- 虛擬執行緒 (Project Loom / JDK 21):輕量級用戶態線程,阻塞不佔用平台線程,百萬級併發,配合結構化並發 (StructuredTaskScope) 簡化錯誤處理。
五、總結與建議
多執行緒知識點繁雜,建議採用 「原理 → 源碼 → 實戰 → 面試」 四步走:
- 啃透 JUC 核心類源碼 (AQS、ConcurrentHashMap、ThreadPoolExecutor)。
- 寫 Demo 驗證行為 (死鎖、活鎖、線程池擴容、CAS 失敗重試)。
- 壓測對比 (LongAdder vs AtomicLong、虛擬線程 vs 平台線程)。
- 整理成自己的知識圖譜,定期複習。
掌握這 40 點,應付 90% 以上的 Java 併發面試與實際開發難題綽綽有餘。