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

Java Timer 與 TimerTask 實作排程任務完整範例:延遲、定點、週期執行

     編輯:Java 相關知識

Java 排程三大核心場景

java.util.Timer 與 TimerTask 是 JDK 內建的輕量級排程工具,適合簡單的單機定時需求。本文示範三種最常見的排程模式。

完整程式碼

package com.example.timer;

import java.awt.Desktop;
import java.io.*;
import java.net.URI;
import java.nio.charset.Charset;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Timer;
import java.util.TimerTask;

public class TimerTaskDemo {

    public static void main(String[] args) throws ParseException {
        Timer timer = new Timer();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

        // 1. 延遲 1 秒執行一次
        timer.schedule(new TimerTask() {
            @Override public void run() {
                System.out.println("⏱ 時間流逝 1 秒!");
            }
        }, 1000); // delay ms

        // 2. 指定絕對時間執行一次
        timer.schedule(new TimerTask() {
            @Override public void run() {
                try {
                    Desktop.getDesktop().browse(new URI("https://www.baidu.com"));
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }, sdf.parse("2025-12-31 23:59:59")); // 指定 Date

        // 3. 延遲 10 秒啟動,之後每 5 秒執行一次(固定頻率)
        timer.schedule(new TimerTask() {
            @Override public void run() {
                try {
                    Process p = Runtime.getRuntime().exec("ping www.baidu.com");
                    try (BufferedInputStream in = new BufferedInputStream(p.getInputStream());
                         BufferedReader br = new BufferedReader(new InputStreamReader(in, Charset.forName("GBK")))) {
                        String line;
                        while ((line = br.readLine()) != null) {
                            System.out.println(line);
                        }
                    }
                    if (p.waitFor() != 0) {
                        System.err.println("指令執行失敗,exit code: " + p.exitValue());
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }, 10_000, 5_000); // delay, period

        // 程式不會自動結束,需手動停止(或加 timer.cancel() 條件)
    }
}

三種 schedule 簽名差異

方法參數行為適用場景
schedule(task, delay)delay (ms)延遲 delay 後執行一次啟動延遲初始化、一次性提醒
schedule(task, time)Date在指定時刻執行一次定點備份、定時發報
schedule(task, delay, period)delay, period (ms)延遲 delay 後,每 period 執行一次(固定頻率,不補償)心跳、輪詢、定期清理
scheduleAtFixedRate(task, delay, period)delay, period (ms)延遲 delay 後,每 period 執行一次(固定速率,會補償)精準週期、動畫幀率

關鍵差異:schedule(固定頻率)若上次執行超時,下一次會在「上次結束 + period」啟動;scheduleAtFixedRate(固定速率)會嘗試在「首次啟動 + N×period」啟動,若超時會連續執行追趕進度。

常見坑點與最佳實踐

  • 單執行緒序列化:Timer 內部只有一個背景執行緒,任務執行時間過長會阻塞後續任務。耗時任務請用 ScheduledExecutorService。
  • 異常吞沒:TimerTask.run() 拋出未捕獲異常會導致整個 Timer 執行緒死亡,後續所有任務停止。務必在 run() 內 try-catch 並記錄日誌。
  • 關閉資源:應用關閉時呼叫 timer.cancel(),並處理 TimerTask 內的 I/O 資源釋放。
  • 時間精度:Timer 精度約 10-15ms,毫秒級嚴格週期請用 ScheduledExecutorService 或 Quartz。
  • 時區與夏令時:使用 Date 時注意時區,建議改用 Instant / ZonedDateTime + ScheduledExecutorService。

進階替代方案

  • ScheduledExecutorService:JDK 5+,執行緒池、支援 Runnable/Callable、可取消單一任務、異常隔離。
  • Spring @Scheduled:整合 Spring 容器、支援 Cron 表達式、固定延遲/速率。
  • Quartz:分散式、持久化、叢集、Cron、誤火處理、監控介面。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved