定義一個類繼承 java.lang.Thread,重寫 run() 方法放入執行邏輯,建立實例後呼叫 start() 即可啟動新線程。JVM 會在新線程中自動呼叫 run()。
public class FirstThread extends Thread {
public static void main(String[] args) {
FirstThread ft = new FirstThread();
ft.start(); // 啟動子線程
// 主線程繼續執行
for (int i = 0; i < 10; i++) {
try { Thread.sleep(1000); } catch (InterruptedException e) {}
System.out.println("main:" + i);
}
}
@Override
public void run() {
for (int i = 0; i < 10; i++) {
try { Thread.sleep(1000); } catch (InterruptedException e) {}
System.out.println("run:" + i);
}
}
}
run:0
main:0
main:1
run:1
main:2
run:2
...
輸出交錯出現,證明 main 與 run 兩條線程真正並發執行。順序不固定,取決於作業系統排程器。
start():啟動新線程,JVM 分配棧幀、PC 計數器,非阻塞立即返回。run():普通方法呼叫,在當前線程同步執行,不會開啟新線程。❌ 錯誤:ft.run(); → 單線程循序執行。
✅ 正確:ft.start(); → 多線程並發。
new FirstThread(),物件建立但未啟動。start() 後,進入就緒/運行狀態,由 OS 排程。run() 方法正常返回或拋出未捕獲異常,線程終止,資源釋放。JVM 只有在所有非守護線程結束後才退出。主線程 main() 結束不代表程式結束——若子線程還在跑,程式會繼續運行。
// 獨立線程類:單一職責,可複用
public class ThirdThread extends Thread {
@Override
public void run() {
for (int i = 0; i < 10; i++) {
try { Thread.sleep(1000); } catch (InterruptedException e) {}
System.out.println("run:" + i);
}
}
}
// 使用端:隨時隨地啟動多個實例
public class Test {
public static void main(String[] args) {
new ThirdThread().start(); // 線程 1
new ThirdThread().start(); // 線程 2,獨立運行
// 主線程邏輯...
}
}
Thread t = new ThirdThread();
t.start(); // OK
t.start(); // ❌ IllegalThreadStateException:線程已啟動過
若需重複執行同樣邏輯,請 new 多個實例,或改用 Runnable + 線程池。
public class SecondThread extends Thread {
public static void main(String[] args) {
new SecondThread().start();
print("main:");
}
@Override public void run() { print("run:"); }
private static void print(String prefix) {
for (int i = 0; i < 10; i++) {
try { Thread.sleep(1000); } catch (InterruptedException e) {}
System.out.println(prefix + i);
}
}
}
run() 呼叫的 print() 同樣在新線程中執行,結構清晰、零重複。
| 優點 | 缺點 |
|---|---|
| 語法簡單、直觀、適合入門教學 | 佔用單繼承名額,任務與執行緒強耦合 |
| 可直接存取 this 訪問線程屬性 | 難以複用邏輯、難以配合線程池 |
建議:教學/原型階段可用;正式專案請優先選擇 實作 Runnable + ExecutorService。