Java 語言內建多執行緒支援,Thread 與 Runnable 是兩大核心 API。本文以最簡單的「雙執行緒交替列印」為例,詳細講解執行緒建立、啟動、生命週期、併發執行特性,並對比兩種實作方式的優劣。
public class TwoThread extends Thread {
@Override
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println("New thread: " + i);
}
}
public static void main(String[] args) {
TwoThread tt = new TwoThread();
tt.start(); // 啟動新執行緒,進入 run()
for (int i = 0; i < 10; i++) {
System.out.println("Main thread: " + i);
}
}
}
public class Task implements Runnable {
@Override
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println("Runnable task: " + i);
}
}
public static void main(String[] args) {
Thread t = new Thread(new Task());
t.start();
// 主執行緒繼續...
}
}
| 維度 | extends Thread | implements Runnable |
|---|---|---|
| 繼承限制 | 單繼承,無法繼承其他類 | 無限制,可繼承其他類 |
| 職責分離 | 執行緒控制與任務邏輯耦合 | 任務邏輯獨立,可復用 |
| 資源共享 | 較難共享同一任務實例 | 易於多執行緒共享同一 Runnable |
| 適用場景 | 簡單獨立任務、教學演示 | 生產代碼、線程池、併發框架 |
start():啟動執行緒,**非同步返回**,JVM 排程稍後調用 run()。run():任務邏輯入口,**直接調用不會啟動新執行緒**(變成普通方法呼叫)。sleep(ms):讓出 CPU,進入 TIMED_WAITING,不釋放鎖。join():等待目標執行緒結束。interrupt():中斷阻塞/睡眠執行緒,需配合 Thread.interrupted() 檢查。多核 CPU 可真並行;單核透過時間片輪轉模擬並發。**執行緒間指令交織順序不可預測**,共享資料必須同步(synchronized、Lock、volatile、Atomic*)。
ExecutorService 線程池(Executors.newFixedThreadPool、newVirtualThreadPerTaskExecutor (JDK 21))。CompletableFuture 實現非阻塞鏈式編程。Thread 實例,減少資源洩漏風險。