線程生命週期五大狀態
- 新建:
new Thread()
- 可執行:
start() 後,等待 CPU 調度
- 運行:獲得 CPU 時間片,執行
run()
- 阻塞:
- 等待阻塞:
wait()
- 同步阻塞:獲取
synchronized 鎖失敗
- 其他阻塞:
sleep()、join()、I/O
- 死亡:
run() 正常結束或拋出未捕獲異常
實現多線程兩大途徑
| 方式 | 關鍵點 | 優缺點 |
| 繼承 Thread | override run() | 單繼承限制,無法共享資源 |
| 實現 Runnable | implements Runnable + new Thread(runnable) | 支援多實現、易共享資源(推薦) |
start() vs run()
start():啟動新線程,JVM 呼叫本地方法 start0(),新線程執行 run()。
run():普通方法調用,在當前線程執行,不會開啟新線程。
同步機制:synchronized
三種用法
- 同步實例方法:
public synchronized void foo() 鎖 this
- 同步靜態方法:
public static synchronized void bar() 鎖 Class 物件
- 同步代碼塊:
synchronized(obj) { ... } 鎖指定物件,粒度更細
鎖規則
- 同一物件的同步方法/塊互斥。
- 同步不阻礙非同步代碼執行。
- 實例鎖 vs 類鎖(static)互不干擾。
線程通訊:wait / notify / notifyAll
- 必須在
synchronized 區塊內呼叫,否則拋 IllegalMonitorStateException。
wait():釋放鎖,進入等待集。
notify():喚醒單一等待線程;notifyAll():喚醒全部。
- 被喚醒線程需重新獲取鎖才能繼續執行。
輔助方法對比
| 方法 | 狀態轉換 | 釋放鎖 | 所屬類 |
| wait() | 運行→等待 | 是 | Object |
| sleep() | 運行→休眠(阻塞) | 否 | Thread |
| yield() | 運行→可執行 | 否 | Thread |
| join() | 運行→阻塞(等待目標線程結束) | 否 | Thread |
線程中斷
volatile 關鍵字
- 可見性:寫入 volatile 立即刷新到主記憶體;讀取強制從主記憶體載入。
- 非原子性:
volatile++ 非原子,需配合 AtomicInteger 或 synchronized。
- 禁止指令重排(JMM happens-before)。
ThreadLocal 線程封閉
每個線程擁有獨立副本,避免共享衝突。典型用法:資料庫連線、Session 上下文、事務 ID 傳遞。
ThreadLocal<Connection> tl = ThreadLocal.withInitial(() -> DriverManager.getConnection(url));
// 使用
Connection conn = tl.get();
// 結束必須清理,防記憶體洩漏
tl.remove();
生產者-消費者經典模型
class Buffer {
private final Queue<Integer> q = new LinkedList<>();
private final int capacity;
public Buffer(int cap) { capacity = cap; }
public synchronized void produce(int v) throws InterruptedException {
while (q.size() == capacity) wait();
q.offer(v);
notifyAll();
}
public synchronized int consume() throws InterruptedException {
while (q.isEmpty()) wait();
int v = q.poll();
notifyAll();
return v;
}
}
線程池與 Executor 框架
- 核心參數:corePoolSize、maximumPoolSize、keepAliveTime、workQueue、ThreadFactory、RejectedExecutionHandler。
- 常用靜態工廠:
Executors.newFixedThreadPool、newCachedThreadPool、newSingleThreadExecutor、newScheduledThreadPool。
- 生產環境建議自定義 ThreadPoolExecutor,明確拒絕策略與佇列界限。
總結:多線程開發黃金法則
- 優先使用
Runnable + 線程池,避免手動管理線程。
- 共享可變狀態最小化;優先用不可變物件、
ThreadLocal、佇列傳遞資料。
- 同步塊保持最小範圍;避免在同步內呼叫外部方法/阻塞操作。
- 正確處理中斷:捕獲
InterruptedException 後恢復中斷標誌或退出迴圈。
- 善用
java.util.concurrent 高階組件:CountDownLatch、CyclicBarrier、Semaphore、CompletableFuture。
- 上一篇文章: Java 設計模式精講:單例模式與簡單工廠模式深度解析
- 下一篇文章: C# WinForms 視窗最大化不遮擋工作列的正確做法
Copyright ©
程式碼之家 All Rights Reserved