Thread 類別提供兩個關鍵方法:start() 與 run()。兩者**極易混淆**,但語意截然不同,直接影響多線程程式的正確性與效能。
| 方法 | 作用 | 執行緒 | 可重複呼叫 | 底層機制 |
|---|---|---|---|---|
start() | 啟動**新執行緒**,由 JVM 排程執行 run() | 新建執行緒 | 否 (第二次拋 IllegalThreadStateException) | JNI start0() → OS 執行緒建立 |
run() | 僅作為**普通方法**在**當前執行緒**同步執行 | 當前執行緒 (main 等) | 是 | 直接呼叫 target.run() 或空實作 |
public class StartVsRunDemo {
static class MyThread extends Thread {
@Override public void run() {
for (int i = 0; i < 3; i++) {
System.out.printf("%s: i=%d%n", Thread.currentThread().getName(), i);
}
}
}
public static void main(String[] args) {
MyThread t = new MyThread();
t.setName("MyThread");
System.out.println("--- 呼叫 t.run() (同步執行) ---");
t.run(); // 主執行緒直接跑 run()
System.out.println("--- 呼叫 t.start() (啟動新執行緒) ---");
t.start(); // 新執行緒非同步跑 run()
System.out.println("main 結束");
}
}
--- 呼叫 t.run() (同步執行) ---
main: i=0
main: i=1
main: i=2
--- 呼叫 t.start() (啟動新執行緒) ---
main 結束
MyThread: i=0
MyThread: i=1
MyThread: i=2
// Thread.java
public synchronized void start() {
if (threadStatus != 0) throw new IllegalThreadStateException();
group.add(this);
boolean started = false;
try {
start0(); // native 方法,向 OS 申請新執行緒
started = true;
} finally {
if (!started) group.threadStartFailed(this);
}
}
private native void start0(); // JNI 進入點
public void run() {
if (target != null) target.run(); // target 為 Runnable 實例
}
new Thread(() -> {...}).run(); — 未啟動新執行緒,同步阻塞當前線程。new Thread(() -> {...}).start(); — 真正並發執行。new Thread(() -> System.out.println("running")).start();ExecutorService,避免頻繁建立/銷毀 OS 執行緒開銷。優先實作 Runnable 或 Callable,再交給 Thread 或執行緒池執行,優點:
Thread 導致的單一繼承限制。