首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 程式設計入門

Java Timer 定時任務完整指南:schedule vs scheduleAtFixedRate、優雅停機與實戰範本

     編輯:Java 程式設計入門

Timer 兩大調度模式

模式方法簽名特性適用場景
固定延遲schedule(task, delay)
schedule(task, delay, period)
下一次執行時間 = 上一次**實際完成時間** + period。若任務耗時長,間隔自動拉大。輕量級、不嚴格要求頻率的後台清理、同步。
固定頻率scheduleAtFixedRate(task, delay, period)下一次執行時間 = 上一次**理論開始時間** + period。若任務延遲,Timer 會嘗試「追趕」壓縮後續間隔。心跳檢測、即時採樣、嚴格週期業務。

基礎範例:啟動、停止、動態修改參數


public class TimerDemo {
    public static void main(String[] args) throws IOException {
        Timer timer = new Timer();
        MyTask task1 = new MyTask("Task-1");
        MyTask task2 = new MyTask("Task-2");

        timer.schedule(task1, 1000, 2000);           // 1s 後啟動,每 2s
        timer.scheduleAtFixedRate(task2, 2000, 3000); // 2s 後啟動,每 3s 固定頻率

        // 控制台指令互動
        BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
        String line;
        while ((line = in.readLine()) != null) {
            if (line.startsWith("cancel-1")) task1.cancel();
            else if (line.startsWith("cancel-2")) task2.cancel();
            else if (line.startsWith("cancel-all")) { timer.cancel(); break; }
            else task1.setMsg(line); // 動態修改任務行為
        }
    }

    static class MyTask extends TimerTask {
        private String msg = "^_^";
        public void run() { System.out.println(msg); }
        public void setMsg(String m) { msg = m; }
    }
}

關鍵 API 深度解析

  • TimerTask.cancel():取消**單個任務**未來執行,已在執行的不受影響。回傳 boolean 表示是否成功取消 (尚未執行過)。
  • Timer.cancel():取消**所有任務**,釋放 Timer 內部執行緒,**不可重用**,後續 schedule 拋 IllegalStateException。
  • TimerTask.scheduledExecutionTime():取得**理論應執行時間** (毫秒),可用於計算漂移、補償邏輯。
  • Timer.purge():從佇列移除已取消任務,釋放記憶體 (大量動態增刪任務時調用)。

常見坑與對策

問題原因解決
任務拋出未捕獲異常 → Timer 執行緒死亡 → 所有任務停止Timer 單執行緒循環,異常向上傳播終止循環run() 內部 try-catch(Exception e){log} 吞掉所有異常
scheduleAtFixedRate 追趕導致疊併執行任務耗時 > period,Timer 立即排程下一次任務內加 synchronized 或改用 ScheduledExecutorService
JVM 關閉前任務未完成Timer 執行緒非 Daemon (預設)new Timer(true) 建立 Daemon Timer,或關閉鉤子呼叫 timer.cancel()
大量任務 (10k+) 效能下降單執行緒輪詢 TaskQueue (鏈表/堆)遷移至 ScheduledThreadPoolExecutor

現代替代:ScheduledExecutorService (Java 5+)


ScheduledExecutorService ses = Executors.newScheduledThreadPool(2);
ses.scheduleAtFixedRate(() -> System.out.println("beat"), 1, 2, TimeUnit.SECONDS);
// 優雅關閉
ses.shutdown();
ses.awaitTermination(10, TimeUnit.SECONDS);
優勢:執行緒池隔離、支援 Future 取消/查狀態、可配置 ThreadFactory (命名、Daemon)、拋異常不影響其他任務。

選型建議

  • 簡單工具類、單執行緒、無並發:Timer 輕量足夠。
  • 生產系統、多任務、需監控/優雅關閉/異常隔離:直接上 ScheduledExecutorService。
  • 分散式排程、持久化、失敗重試、分片:Quartz、XXL-Job、PowerJob。

Timer 是 Java 早期產物,理解其單執行緒、固定延遲/頻率語義差異,是遷移至現代排程框架的基石。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved