多執行緒是 Java 並發程式設計基石。本文系統整理執行緒建立、控制、同步、通訊與經典問題解決,附完整可執行範例代碼。
| 方式 | 繼承 Thread | 實作 Runnable |
|---|---|---|
| 程式碼結構 | class MyThread extends Thread { run() {...} } | class MyTask implements Runnable { run() {...} } |
| 啟動方式 | new MyThread().start() | new Thread(new MyTask()).start() |
| 資源共享 | 困難 (每個實例獨立欄位) | 容易 (同一 Runnable 實例給多執行緒) |
| 繼承限制 | 單一繼承限制 | 無限制,可再繼承其他類 |
| 設計模式 | — | 代理模式 (Thread 內部持有 Runnable) |
核心差異:Thread.start() 為 native 方法呼叫 OS 建立執行緒,直接呼叫 run() 只是普通方法呼叫,不會啟動新執行緒。
// 基本操作
thread.start(); // 啟動
thread.join(); // 等待結束 (可設 timeout)
thread.sleep(ms); // 休眠 (靜態方法,當前執行緒)
thread.interrupt(); // 中斷標記
thread.isAlive(); // 檢查存活
thread.setDaemon(true); // 守護執行緒 (JVM 結束時自動結束)
thread.setPriority(1-10); // 優先級 (僅建議性)
Thread.yield(); // 禮讓 CPU (靜態方法)
synchronized (this) { // 或共享鎖物件
if (count > 0) {
Thread.sleep(1000);
System.out.println(count--);
}
}
public synchronized void sale() {
if (count > 0) {
Thread.sleep(1000);
System.out.println(count--);
}
}
鎖物件選擇:實例方法鎖 this、靜態方法鎖 ClassName.class、共享資源鎖專用物件。
// 同步方法但無等待通知
public synchronized void set(String name, int age) { ... }
public synchronized void get() { ... }
// 結果:Rollen<=>100, ChunGe<=>100 (資料不一致)、大量重複
class Info {
private boolean flag = false; // false=可生產, true=可消費
public synchronized void set(String name, int age) {
if (!flag) { // 不可生產時等待
try { wait(); } catch (InterruptedException e) { e.printStackTrace(); }
}
this.name = name;
Thread.sleep(100);
this.age = age;
flag = false; // 切換為可消費
notify(); // 喚醒消費者
}
public synchronized void get() {
if (flag) { // 不可消費時等待
try { wait(); } catch (InterruptedException e) { e.printStackTrace(); }
}
Thread.sleep(100);
System.out.println(name + "<=>" + age);
flag = true; // 切換為可生產
notify(); // 喚醒生產者
}
}
輸出結果:完美交替 Rollen<=>20 / ChunGe<=>100,無重複、無遺漏。
Lock.tryLock(timeout) 避免無限等待BlockingQueue、Semaphore、CountDownLatch 替代手動 wait/notify掌握執行緒建立、同步、協作三大核心,配合現代並發套件,即可構建高效穩定的並發應用。