Java 單繼承限制導致「繼承 Thread」無法同時繼承業務基類。業界主流採用實作介面或組合框架方式,靈活解耦「任務邏輯」與「執行機制」。
// 任務類:只負責「做什麼」
public class MyRunnable implements Runnable {
@Override
public void run() {
for (int i = 0; i < 10; i++) {
try { Thread.sleep(1000); } catch (InterruptedException e) { return; }
System.out.println("run:" + i);
}
}
}
// 啟動類:負責「怎麼跑」
public class Test2 {
public static void main(String[] args) {
MyRunnable task = new MyRunnable(); // 1. 建立任務
Thread thread = new Thread(task); // 2. 包裝成線程
thread.start(); // 3. 啟動
// 主線程同步執行其他邏輯
for (int i = 0; i < 10; i++) {
try { Thread.sleep(1000); } catch (InterruptedException e) {}
System.out.println("main:" + i);
}
}
}
new Thread(() -> { ... }).start();Timer:單線程調度器,內部維護一條守護線程。TimerTask:抽象類,實作 Runnable,承載具體任務邏輯。import java.util.*;
public class MyTimerTask extends TimerTask {
private final String prefix;
public MyTimerTask(String prefix) { this.prefix = prefix; }
@Override
public void run() {
for (int i = 0; i < 10; i++) {
try { Thread.sleep(1000); } catch (InterruptedException e) { return; }
System.out.println(prefix + i);
}
}
}
public class Test3 {
public static void main(String[] args) {
Timer timer = new Timer();
TimerTask task = new MyTimerTask("線程1:");
timer.schedule(task, 0); // 0ms 延遲立即執行
}
}
| 方法簽名 | 語義 | 典型場景 |
|---|---|---|
| schedule(task, Date time) | 指定絕對時間點觸發一次 | 每日零點備份 |
| schedule(task, Date first, long period) | 指定時間點首次觸發,之後固定週期 | 每天 10:00 發報表 |
| schedule(task, long delay) | 延遲 delay ms 觸發一次 | 5 秒後關閉閃屏頁 |
| schedule(task, long delay, long period) | 延遲 delay 後首次觸發,之後固定週期 | App 啟動 3 秒後開始每 10 秒心跳 |
Timer t = new Timer();
t.schedule(new MyTimerTask("線程1:"), 1000);
t.schedule(new MyTimerTask("線程2:"), 1000);
// 輸出:線程1 跑完 10 秒後,線程2 才開始
原因:Timer 內部只有一條線程循環取任務執行,前一個任務未結束,後續任務只能排隊等待。
new Timer().schedule(new MyTimerTask("線程1:"), 1000);
new Timer().schedule(new MyTimerTask("線程2:"), 1000);
// 兩條獨立 Timer 線程,真正並行
ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(2);
scheduler.scheduleAtFixedRate(() -> System.out.println("任務1"), 0, 1, TimeUnit.SECONDS);
scheduler.scheduleAtFixedRate(() -> System.out.println("任務2"), 0, 1, TimeUnit.SECONDS);
// 線程池管理、異常隔離、關閉優雅、支援更多調度策略
Runnable + ExecutorService 提交。ScheduledExecutorService(取代 Timer)。