在 Java 並發編程中,線程創建是基礎中的基礎。主要有兩種實現路徑:實現 Runnable 接口與繼承 Thread 類。兩者各有優劣,選型需視業務場景而定。
此方式符合「組合優於繼承」的設計原則,支援多實現,便於資源共享。
public class RocketCountdown implements Runnable {
private int countDown = 10;
@Override
public void run() {
while (countDown-- > 0) {
System.out.println("#" + Thread.currentThread().getName() + "(" + countDown + ")");
}
}
public static void main(String[] args) {
RocketCountdown task = new RocketCountdown();
new Thread(task, "Thread-A").start();
new Thread(task, "Thread-B").start();
System.out.println("火箭發射倒計時:");
}
}
關鍵點:同一 Runnable 實例可被多個線程共享,適合「多線程賣同一張票」等資源競爭場景。
代碼稍顯簡潔,獲取當前線程可直接用 this,但受限於單繼承,擴展性較弱。
public class SimpleCountdown extends Thread {
private int countDown = 10;
@Override
public void run() {
while (countDown-- > 0) {
System.out.println("#" + this.getName() + "(" + countDown + ")");
}
}
public static void main(String[] args) {
new SimpleCountdown().start();
new SimpleCountdown().start();
System.out.println("火箭發射倒計時:");
}
}
| 維度 | Runnable | Thread 繼承 |
|---|---|---|
| 資源共享 | 天然支援,同一任務實例可被多線程執行 | 每個線程獨立實例,共享需額外處理 |
| 繼承限制 | 無,可繼承其他業務類 | 佔用繼承名額,無法再繼承父類 |
| 獲取當前線程 | 需 Thread.currentThread() | 直接用 this |
| 設計模式 | 策略模式,任務與執行分離 | 模板方法模式,耦合度較高 |
最佳實踐:優先選 Runnable(或 Callable),配合線程池使用,符合「任務與執行分離」的現代並發設計哲學。
守護線程(Daemon Thread)是為非守護線程提供後台服務的線程(如 GC、JIT 編譯)。當所有用戶線程結束,JVM 會立即終止,不等待守護線程,且不執行其 finally 塊。
public class DaemonDemo implements Runnable {
@Override
public void run() {
try {
while (true) {
Thread.sleep(1000);
System.out.println("#" + Thread.currentThread().getName() + " 心跳");
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
} finally {
System.out.println("finally 不會被執行"); // 驗證點
}
}
public static void main(String[] args) throws InterruptedException {
for (int i = 0; i < 3; i++) {
Thread t = new Thread(new DaemonDemo(), "Daemon-" + i);
t.setDaemon(true); // 必須在 start() 前設置
t.start();
}
System.out.println("主線程結束,JVM 即將退出");
Thread.sleep(1500); // 給守護線程一點喘息時間
}
}
輸出特徵:主線程結束後,守護線程瞬間消失,finally 無輸出,證明 JVM 強制終止。
setDaemon(true) 必須在 start() 前調用,否則拋 IllegalThreadStateException。ShutdownHook 或非守護線程管理。掌握線程創建的兩種範式與守護線程特性,是寫出高併發、穩健 Java 程式的基石。實戰中:任務用 Runnable,執行交線程池,後台服務用守護線程但謹慎處理資源釋放。