| 維度 | 進程 | 執行緒 |
|---|---|---|
| 定義 | 執行中程式的實例,資源分配基本單位 | 程式執行流最小單位,CPU 調度基本單位 |
| 記憶體 | 獨立位址空間 | 共享進程記憶體(堆、方法區),私有棧、PC 計數器 |
| 建立/切換開銷 | 大 | 小(輕量級進程) |
| 穩定性 | 一個進程崩潰不影響其他 | 一個執行緒崩潰可能導致整個進程退出 |
| 通訊方式 | IPC(管道、Socket、共享記憶體) | 共享變數、wait/notify、Lock、Queue 等 |
NEW (新建) → RUNNABLE (就緒) ↔ RUNNING (執行)
↑ ↓
BLOCKED (阻塞) ← WAITING / TIMED_WAITING
↓
TERMINATED (終止)
new Thread() 建立物件,未呼叫 start()。start() 後,等待 CPU 排程。run()。synchronized 鎖。wait()、join()、sleep()、I/O。run() 正常結束或拋出未捕獲異常。class MyThread extends Thread {
private String name;
public MyThread(String name) { this.name = name; }
@Override public void run() {
for (int i = 0; i < 10; i++) System.out.println(name + " i=" + i);
}
}
public class Demo {
public static void main(String[] args) {
new MyThread("A").start();
new MyThread("B").start();
new MyThread("C").start();
}
}
缺點:Java 單繼承限制,無法繼承其他業務類別。
class MyTask implements Runnable {
private String name;
public MyTask(String name) { this.name = name; }
@Override public void run() { /* 同前 */ }
}
public class Demo {
public static void main(String[] args) {
new Thread(new MyTask("A")).start();
new Thread(new MyTask("B")).start();
new Thread(new MyTask("C")).start();
}
}
優點:避免單繼承限制,任務與執行緒控制分離,方便傳入執行緒池。
class MyTask implements Callable<String> {
@Override public String call() throws Exception {
// 模擬賣票
for (int i = 10; i > 0; i--) System.out.println("剩餘票數:" + i);
return "售罄";
}
}
public class Demo {
public static void main(String[] args) throws Exception {
FutureTask<String> ft1 = new FutureTask<>(new MyTask());
FutureTask<String> ft2 = new FutureTask<>(new MyTask());
new Thread(ft1).start();
new Thread(ft2).start();
System.out.println("執行緒1結果:" + ft1.get()); // 阻塞等待結果
System.out.println("執行緒2結果:" + ft2.get());
}
}
關鍵點:FutureTask 實作 RunnableFuture → Runnable,可直接丟給 Thread;get() 會阻塞直到任務完成。
start() 而非 run()?start():原生方法,向 OS 申請新執行緒,完成後由 JVM 呼叫 run()。run():單純方法呼叫,仍在主執行緒中循序執行,不具備多執行緒特性。start0() 為 native,交由 JVM 依平台實作(Windows/Linux 不同)。| 誤區 | 正確做法 |
|---|---|
| 同一 Thread 物件呼叫兩次 start() | 會拋 IllegalThreadStateException,一個物件只能啟動一次。 |
| 在 run() 中直接操作 UI(Swing/JavaFX) | 需用 SwingUtilities.invokeLater / Platform.runLater 切回 UI 執行緒。 |
| 大量建立 Thread 物件 | 使用 ExecutorService 執行緒池,控制併發數、重用執行緒。 |
| 共享變數未同步 | 用 volatile、Atomic*、synchronized、Lock 保證可見性與原子性。 |
掌握「進程/執行緒差異、五大狀態流轉、三種實作方式優劣、start() 底層原理」是 Java 併發編程的基石。實務上首選 Runnable + 線程池,需回傳值用 Callable + Future,複雜協作再引入 CompletableFuture、CountDownLatch、Semaphore 等高階工具。