Java 多線程面試 52 題精選:從基礎到進階的系統化複習指南
多線程與併發是 Java 面試的「硬骨頭」,也是高併發系統設計的基石。本文精選 52 道高頻面試題,按**基礎概念、線程創建與控制、鎖與同步、JMM 與 volatile、線程池、併發容器、進階原理**七大模塊分類,附核心知識點解析與答案線索,助你構建完整知識體系。
一、基礎概念篇
- 什麼是線程? 操作系統調度的最小單位,進程內的實際執行單元,共享進程堆內存,擁有獨立棧。
- 線程 vs 進程? 進程獨立內存空間,線程共享堆/方法區,私有棧/程序計數器。上下文切換線程更輕量。
- 實現線程兩種方式? 繼承
Thread / 實現 Runnable。後者優勢:避免單繼承限制,分離任務與執行,適合線程池。
- start() vs run()?
start() 啟動新線程並異步調用 run();直接調用 run() 同步執行於當前線程。
二、線程創建與控制篇
- Runnable vs Callable?
Callable.call() 有返回值、可拋異常,配合 FutureTask 獲取結果。
- CyclicBarrier vs CountDownLatch? 前者可重用、支持屏障動作;後者一次性、單純倒計時。
- 如何停止線程? 無安全停止 API。標準模式:
volatile boolean running 標誌位 + interrupt() 中斷阻塞操作。
- 線程異常處理? 未捕獲異常導致線程終止。可設置
Thread.UncaughtExceptionHandler 統一處理。
- wait/notify 為什麼在 Object? 鎖屬於對象,非線程。調用前必須持有對象鎖,否則拋
IllegalMonitorStateException。
- 為什麼 wait 在循環中? 防止虛假喚醒、錯誤喚醒。循環檢查條件滿足才繼續。
三、JMM 與 volatile 篇
- Java 內存模型 (JMM)? 定義線程操作內存的規範,核心是 **happens-before** 規則(程序次序、鎖、volatile、線程啟動/終止、對象構造/終結、傳遞性)。
- volatile 語義? ① 可見性:寫入對後續讀取可見 ② 禁止指令重排序。**不保證原子性**(如
count++ 非原子)。
- volatile vs AtomicInteger? 前者只保證可見/有序;後者 CAS 保證原子操作(
getAndIncrement())。
四、鎖與同步篇
- synchronized vs ReentrantLock? 前者 JVM 內置、自動釋放、可重入;後者 API 級、可中斷、公平鎖、條件變量、性能早期優勢現已縮小。
- 死鎖四條件與預防? 互斥、請求保持、不剝奪、循環等待。破環循環等待(統一加鎖順序)最實用。
- 活鎖 vs 死鎖? 活鎖線程狀態持續變化但無法推進(如走廊雙人互讓)。
- Thread.holdsLock(obj)? 判斷當前線程是否持有對象鎖。
- 獲取線程堆棧? Windows
Ctrl+Break、Linux kill -3 pid、jstack pid。
- 控制線程棧大小?
-Xss (如 -Xss256k)。
五、線程池與併發容器篇
- 為什麼用線程池? 降低創建銷毀開銷、控制併發度、避免 OOM、支持定時/周期任務。
- 核心參數? core/maxPoolSize、keepAliveTime、workQueue、ThreadFactory、RejectedExecutionHandler。
- submit vs execute? 前者返回
Future、異常包裹;後者 void、異常拋給 UncaughtExceptionHandler。
- 隊列滿拋 RejectedExecutionException? 默認
AbortPolicy,可自定義 CallerRunsPolicy 等。
- ConcurrentHashMap 並發度? JDK 7 Segment 鎖(默認 16);JDK 8 CAS + synchronized + 紅黑樹,無並發度概念。
- 同步集合 vs 併發集合? 前者粗粒度鎖(Vector/Collections.synchronizedList);後者細粒度/無鎖(ConcurrentHashMap/CopyOnWriteArrayList),擴展性強。
- ReadWriteLock? 讀共享/寫獨占,
ReentrantReadWriteLock 實現,適合讀多寫少場景。
- BlockingQueue 實現生產者消費者?
put/take 阻塞協調,無需手動 wait/notify。
六、進階原理與最佳實踐篇
- ThreadLocal 原理? 每線程獨有
ThreadLocalMap,Key 為弱引用 ThreadLocal,防內存洩漏需手動 remove()。
- FutureTask 狀態機? NEW → COMPLETING → NORMAL/EXCEPTIONAL → INTERRUPTING → INTERRUPTED。
- ForkJoinPool 工作竊取? 雙端隊列,任務拆分遞歸,空閒線程竊取他人任務,適合計算密集型遞歸任務。
- 雙重檢查鎖單例?
volatile 禁止指令重排,JDK 5+ 修復語義後可用,但枚舉單例更簡潔安全。
- 不可變對象優勢? 天然線程安全、無需同步、可自由共享。構建要點:final 字段、無 setter、防禦性拷貝。
- 忙循環? 不放棄 CPU 的空循環等待,保留緩存熱度,適用於極短等待、多核系統。
- 同步塊異常釋放鎖? **無論正常退出或異常退出,鎖自動釋放**,這是 synchronized 優於手動 Lock 的便利處。
- 三大最佳實踐? ① 有意義線程名 ② 縮小同步範圍(塊優於方法) ③ 優先用併發工具類/併發集合,少寫 wait/notify。
七、面試加分回答模板
| 題目 | 核心加分點 |
| volatile | 引用 JMM happens-before、指令重排、雙重檢查鎖應用 |
| 線程池參數 | 結合業務場景解釋:CPU 密集 vs IO 密集、隊列選擇、拒絕策略 |
| 死鎖排查 | jstack 分析、統一加鎖順序、tryLock 超時、避免嵌套鎖 |
| ThreadLocal 洩漏 | 弱引用 Key、Entry 強引用 Value、線程池復用導致、手動 remove |
八、總結
多線程知識體系龐大,面試考察重點在於:**原理理解深度**、**實戰排查經驗**、**工程化最佳實踐**。建議:
- 按模塊系統複習,畫思維導圖串聯知識點
- 手寫核心代碼:生產者消費者、線程池簡化版、雙重檢查鎖
- 實操
jstack/VisualVM/Arthas 排查死鎖、CPU 飆高、線程洩漏
- 閱讀《Java 併發編程實戰》、《Effective Java》併發章節、JDK 源碼 (AQS、ThreadPoolExecutor、ConcurrentHashMap)
掌握這 52 題核心邏輯,配合實戰經驗,Java 併發面試將不再是攔路虎,而是展示技術深度的舞臺。