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

Java Timer 定時器完整指南:從基礎到企業級應用

     編輯:Java 程式設計入門

Timer 核心類別結構

  • java.util.Timer:排程器,維護任務隊列,單一背景執行緒循環執行
  • java.util.TimerTask:抽象類別,實現 Runnable,需重寫 run() 定義任務邏輯

四種排程模式完整解析

方法簽名行為適用場景
schedule(TimerTask task, long delay)延遲 delay 毫秒後執行一次一次性延遲任務(如啟動後初始化)
schedule(TimerTask task, Date time)在指定時間 time 執行一次固定時間點觸發(如每日零點備份)
schedule(TimerTask task, long delay, long period)延遲 delay 後,每 period 重複執行固定頻率重複任務(如每分鐘心跳檢測)
schedule(TimerTask task, Date firstTime, long period)在 firstTime 首次執行,之後每 period 重複指定啟動時間的週期性任務
scheduleAtFixedRate(...)固定頻率執行,若任務延遲會追趕執行時間敏感型週期任務(如每秒採樣)

實戰程式碼範例

基礎延遲任務

public class DelayedTaskDemo {
    public static void main(String[] args) {
        Timer timer = new Timer();
        
        // 3 秒後執行一次
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                System.out.println("延遲任務執行: " + new Date());
            }
        }, 3000);
        
        // 主執行緒等待,否則 JVM 可能退出
        try { Thread.sleep(5000); } catch (InterruptedException e) {}
        timer.cancel(); // 釋放資源
    }
}

週期性任務

public class PeriodicTaskDemo {
    public static void main(String[] args) {
        Timer timer = new Timer();
        
        // 立即啟動,每 2 秒執行一次
        timer.scheduleAtFixedRate(new TimerTask() {
            int count = 0;
            @Override
            public void run() {
                System.out.printf("週期任務 #%d: %s%n", ++count, new Date());
                if (count >= 5) {
                    timer.cancel(); // 任務內部取消排程器
                }
            }
        }, 0, 2000);
    }
}

指定時間執行

public class FixedTimeTaskDemo {
    public static void main(String[] args) {
        Timer timer = new Timer();
        
        // 計算下一個整點時間
        Calendar cal = Calendar.getInstance();
        cal.add(Calendar.HOUR, 1);
        cal.set(Calendar.MINUTE, 0);
        cal.set(Calendar.SECOND, 0);
        cal.set(Calendar.MILLISECOND, 0);
        Date nextHour = cal.getTime();
        
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                System.out.println("整點報時: " + new Date());
            }
        }, nextHour, 3600_000); // 之後每小時執行
    }
}

Timer 關鍵特性與限制

企業級應用:Web 專案整合

ServletContextListener 啟動排程

@WebListener
public class SchedulerInitializer implements ServletContextListener {
    private Timer timer;
    
    @Override
    public void contextInitialized(ServletContextEvent sce) {
        timer = new Timer(true); // daemon 執行緒,不阻止 JVM 關閉
        
        // 每日清理過期 Session
        timer.scheduleAtFixedRate(new TimerTask() {
            @Override
            public void run() {
                try {
                    SessionCleaner.cleanExpiredSessions();
                } catch (Exception e) {
                    // 必須捕獲異常,防止 Timer 執行緒死亡
                    log.error("Session 清理失敗", e);
                }
            }
        }, calculateFirstMidnight(), 24 * 3600_000);
    }
    
    @Override
    public void contextDestroyed(ServletContextEvent sce) {
        timer.cancel(); // 優雅關閉
    }
    
    private Date calculateFirstMidnight() { /* 計算下一個零點 */ }
}

現代替代方案對比

特性說明
單執行緒模型所有任務共用一個背景執行緒,長時間任務會阻塞後續任務
異常處理任務拋出未捕獲異常會導致 Timer 執行緒終止,所有排程任務失效
時間漂移schedule 固定延遲,累積誤差;scheduleAtFixedRate 固定頻率,會追趕
非持久化JVM 重啟後排程丟失,無法應對叢集環境
無事務支援任務執行不在事務上下文中
方案優點缺點推薦場景
Timer輕量、標準庫、零依賴單執行緒、無持久化、異常脆弱簡單獨立應用、單機定時
ScheduledExecutorService執行緒池、異常隔離、靈活關閉無持久化、無叢集支援Spring 以前的標準替代
Spring @Scheduled聲明式、支援 Cron、整合事務依賴 Spring、單機模式Spring/Spring Boot 專案首選
Quartz持久化、叢集、Cron、監控配置複雜、重量級企業級、叢集、高可靠需求
XXL-Job分散式、Web 控制台、分片、故障轉移需部署調度中心微服務架構、跨語言、運維友好

Spring Boot 整合範例

@Configuration
@EnableScheduling
public class SchedulerConfig implements SchedulingConfigurer {
    @Override
    public void configureTasks(ScheduledTaskRegistrar registrar) {
        registrar.setScheduler(Executors.newScheduledThreadPool(10));
    }
}

@Component
public class BusinessScheduler {
    // 每日 02:00 執行
    @Scheduled(cron = "0 0 2 * * ?")
    public void dailyReport() {
        reportService.generateDailyReport();
    }
    
    // 固定頻率 5 分鐘
    @Scheduled(fixedRate = 5 * 60 * 1000)
    public void healthCheck() {
        monitorService.checkSystemHealth();
    }
}

最佳實踐總結

  1. 任務邏輯務必 try-catch:防止單一任務異常導致整個 Timer 失效
  2. 使用 daemon 執行緒:new Timer(true),不阻塞 JVM 關閉
  3. 避免長時間任務:耗時操作提交到執行緒池異步處理
  4. 優雅關閉:timer.cancel() + timer.purge() 清除已取消任務
  5. 生產環境首選 Spring @Scheduled 或 Quartz:功能完善、社群活躍
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved