在 Java 高併發編程的領域中,多線程是核心基石。本文基於「煉數成金」課程體系,系統梳理多線程的基本概念、核心操作、線程狀態流轉、同步機制等關鍵知識點,旨在為開發者構建清晰、實用的多線程知識體系。
線程是進程內部的執行單元。一個進程可以包含多個線程,它們共享進程的內存空間與資源,但擁有獨立的程序計數器、棧和局部變量。使用線程的根本原因在於:進程切換屬於重量級操作,資源消耗極大,併發能力受限;而線程作為更細粒度的調度單元,輕量級且高效,因此成為併發設計的主流選擇。
在 Java 中,線程模型映射到操作系統原生線程(內核級線程),JVM 負責將 Java 線程一一對應到 OS 線程,實現真正的並行執行。
Java 線程擁有六種核心狀態,狀態流轉如下:
new Thread()),尚未啟動。start() 後進入就緒狀態,等待 CPU 時間片;包含「運行中」與「就緒」兩種子狀態。wait()、join() 無參版本,無限期等待其他線程通知。sleep()、wait(timeout)、join(timeout),超時自動轉回 RUNNABLE。run() 方法執行完畢或拋出未捕獲異常,線程結束。// 正確方式:啟動新線程
Thread t1 = new Thread("t1") {
@Override public void run() {
System.out.println(Thread.currentThread().getName()); // 輸出 t1
}
};
t1.start();
// 錯誤方式:直接調用 run(),實為普通方法調用,不會開啟新線程
Thread t2 = new Thread("t2") {
@Override public void run() {
System.out.println(Thread.currentThread().getName()); // 輸出 main
}
};
t2.run();
核心區別:start() 會請求 OS 創建新線程並調用 run();直接調用 run() 仍在當前線程執行。
實現 run() 兩種模式:
stop()Thread.stop() 已被棄用,因其會強制釋放所有鎖,導致數據不一致且不拋出異常,極難排查。正確做法是採用協作式中斷機制。
Java 提供三個核心方法:
interrupt():設置中斷標誌位為 true。isInterrupted():檢查標誌位,不清除。Thread.interrupted():檢查並清除當前線程標誌位。關鍵點:中斷只是「請求」,線程需主動檢查標誌位並決定如何響應。
// 非阻塞場景:輪詢標誌位
public void run() {
while (!Thread.currentThread().isInterrupted()) {
// 業務邏輯
Thread.yield();
}
}
// 阻塞場景:捕獲 InterruptedException 並重新設置標誌位
public void run() {
while (true) {
if (Thread.currentThread().isInterrupted()) break;
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt(); // 重新設置標誌位
break;
}
}
}
suspend()/resume()這對方法不釋放鎖,極易導致死鎖。例如線程 A 持有鎖並 suspend(),線程 B 嘗試獲取同一鎖會永久阻塞;若 resume() 先於 suspend() 執行,線程將永久掛起。替代方案:使用 wait()/notify() 或 LockSupport.park()/unpark()。
join() 與 yield()while(isAlive()) wait(0);線程結束時 JVM 自動調用 notifyAll() 喚醒等待者。注意:避免在 Thread 實例上直接使用 wait/notify,防止干擾 JVM 內部機制。守護線程(Daemon Thread)在後台默默服務,如 GC、JIT 編譯線程。當 JVM 中僅剩守護線程時,JVM 自動退出。
Thread dt = new Thread(() -> {
while (true) System.out.println("daemon running");
});
dt.setDaemon(true); // 必須在 start() 前設置
dt.start();
// 主線程結束,守護線程隨之終止,無輸出
Java 定義三級優先級:MIN_PRIORITY=1、NORM_PRIORITY=5、MAX_PRIORITY=10。優先級高的線程獲得 CPU 時間片機率較大,但不保證必然先執行完,受 OS 調度策略影響。
synchronized 三種加鎖方式| 方式 | 鎖對象 | 適用場景 |
|---|---|---|
同步代碼塊 synchronized(obj) | 指定對象 | 精細控制鎖粒度 |
| 同步實例方法 | 當前實例 this | 實例級別同步 |
| 同步靜態方法 | 當前類 Class 對象 | 類級別同步,跨實例生效 |
wait()/notify() 核心規則IllegalMonitorStateException。wait() 釋放鎖並進入等待集;notify() 隨機喚醒一個,notifyAll() 喚醒所有。wait() 返回繼續執行。多線程是 Java 高併發的基石。掌握線程生命週期、正確的啟動/終止/中斷姿勢、守護線程特性、優先級影響以及同步核心機制,是編寫健壯併發程式的前提。實戰中應優先使用 Runnable + 線程池、協作式中斷、java.util.concurrent 高級組件,避免直接操作底層線程 API。