Runnable 介面,定義任務邏輯Runnable 實例傳給 Thread 建構子start() 啟動執行緒(非 run())main)與子執行緒並發執行,輸出交錯class Task implements Runnable {
@Override
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println(Thread.currentThread().getName() + " 我是: " + i);
// 可選:短暫睡眠增加交錯機會
// try { Thread.sleep(1); } catch (InterruptedException ignored) {}
}
}
}
public class ThreadAlternate {
public static void main(String[] args) {
Task task = new Task(); // 單一任務實例
Thread t1 = new Thread(task, "執行緒-1");
Thread t2 = new Thread(task, "執行緒-2");
t1.start(); // 啟動執行緒 1
t2.start(); // 啟動執行緒 2
// 主執行緒也執行相同邏輯
for (int i = 0; i < 10; i++) {
System.out.println(Thread.currentThread().getName() + " 我是: " + i);
}
}
}
main 執行緒: new Task() → new Thread(t1) → new Thread(t2) → t1.start() → t2.start() → for 迴圈輸出 t1 執行緒 (並發): run() → for 迴圈輸出 t2 執行緒 (並發): run() → for 迴圈輸出 輸出順序:非確定性,取決於 OS 排程器,典型呈現交錯模式
Runnable 給 Thread?Thread 負責「執行緒生命週期管理」(啟動、排程、結束)Runnable 負責「任務邏輯」(run() 方法)Thread 本身也實作 Runnable,繼承 Thread 並覆寫 run() 同樣可行,但不推薦(單一繼承限制)main 我是: 0 執行緒-1 我是: 0 執行緒-2 我是: 0 main 我是: 1 執行緒-1 我是: 1 執行緒-2 我是: 1 ...
若需主執行緒等待子執行緒結束:
t1.start(); t2.start();
try { t1.join(); t2.join(); } catch (InterruptedException e) { e.printStackTrace(); }
System.out.println("所有子執行緒結束");
| 誤區 | 正確做法 |
|---|---|
直接呼叫 run() | 呼叫 start() 才會開新執行緒 |
| 以為輸出固定順序 | 多執行緒輸出本質非確定性 |
| 共享資料未同步 | 需 synchronized/volatile/Atomic* |
| 主執行緒結束程式就結束 | 非守護執行緒未結束時 JVM 不退出 |