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

Java TimerTask 定時任務獲取網路資料實戰指南

     編輯:Java 相關知識

前言:為什麼選 TimerTask?

java.util.Timer + TimerTask 是 JDK 內建的輕量級排程器,適合單機、簡單、非分散式的週期性任務(如每 5 分鐘抓取一次 API、每天凌晨備份資料)。若需分散式、高可用、彈性排程,請改用 Quartz、Spring @Scheduled 或 XXL-JOB。

核心元件關係

  • Timer:單一背景執行緒(守護執行緒),維護任務隊列,按時間觸發。
  • TimerTask:實作 Runnable 的抽象類,覆寫 run() 放入業務邏輯。
  • 排程方式:
    • schedule(task, delay):一次性延遲執行
    • schedule(task, delay, period):固定延遲週期(上次結束 → 等 period → 下次開始)
    • scheduleAtFixedRate(task, delay, period):固定頻率週期(上次開始 → 等 period → 下次開始)

完整範例:每 30 秒抓取 HTTP API 並解析 JSON

import java.io.*;
import java.net.*;
import java.util.*;
import com.fasterxml.jackson.databind.*;

public class NetworkDataFetcher {
    private static final String API_URL = "https://api.example.com/data";
    private static final ObjectMapper MAPPER = new ObjectMapper();
    private static final Timer TIMER = new Timer(true); // 守護執行緒,JVM 退出自動結束

    public static void main(String[] args) {
        TimerTask task = new TimerTask() {
            @Override public void run() {
                try {
                    fetchAndProcess();
                } catch (Exception e) {
                    logError("任務執行異常", e);
                }
            }
        };
        // 啟動:立即執行一次,之後每 30 秒固定頻率
        TIMER.scheduleAtFixedRate(task, 0, 30_000);
        Runtime.getRuntime().addShutdownHook(new Thread(TIMER::cancel));
    }

    private static void fetchAndProcess() throws IOException {
        URL url = new URL(API_URL);
        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
        conn.setRequestMethod("GET");
        conn.setConnectTimeout(5000);
        conn.setReadTimeout(10000);
        conn.setRequestProperty("Accept", "application/json");

        try (InputStream is = conn.getInputStream()) {
            JsonNode root = MAPPER.readTree(is);
            // 業務處理:例如提取特定欄位、存入資料庫、發送通知
            String value = root.path("data").path("value").asText();
            System.out.printf("[%s] 獲取成功: %s%n", new Date(), value);
        } finally {
            conn.disconnect();
        }
    }

    private static void logError(String msg, Exception e) {
        System.err.printf("[%s] %s: %s%n", new Date(), msg, e.getMessage());
    }
}

關鍵最佳實踐

場景建議理由
任務耗時 > 週期改用 ScheduledExecutorService 多執行緒Timer 單執行緒,前一任務阻塞會延遲後續任務
需彈性停止/暫停保存 TimerTask 參考,呼叫 cancel()Timer.cancel() 會清空所有任務,粒度太粗
異常處理run() 內部 try-catch,記錄日誌不拋出未捕獲異常會導致 Timer 執行緒死亡,所有任務停止
資料庫/HTTP 連線使用連線池,設定連線/讀取超時避免長時間阻塞排程執行緒
JVM 關閉註冊 ShutdownHook 呼叫 timer.cancel()確保資源釋放、非守護執行緒正常結束

進階:ScheduledExecutorService 替代方案(推薦生產環境)

ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor(r -> {
    Thread t = new Thread(r, "DataFetcher");
    t.setDaemon(true); return t;
});
scheduler.scheduleAtFixedRate(() -> {
    try { fetchAndProcess(); }
    catch (Exception e) { logError("任務異常", e); }
}, 0, 30, TimeUnit.SECONDS);
// 關閉:scheduler.shutdown();
  • 支援多執行緒池、彈性關閉、更好的異常隔離、可配合 Future 取消單一任務。
  • Spring Boot 專案直接用 @Scheduled(fixedRate = 30000) + @EnableScheduling 更簡潔。

結語

TimerTask 是輕量級定時任務的入門選擇,但單執行緒、異常脆弱、無持久化限制了其生產適用性。理解其運作機制與避坑指南,能在小型專案、原型驗證、維護腳本中快速落地;正式系統建議遷移至 ScheduledExecutorService 或成熟排程框架。

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