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

Java 定時任務實戰:DelayQueue 與 ScheduledThreadPoolExecutor 詳解

     編輯:Java 相關知識

在 Java 並發編程中,延遲執行與定時排程是常見需求。JDK 5.0 引入的 java.util.concurrent 套件提供了兩種核心方案:DelayQueue 適合構建自定義的延遲任務隊列,而 ScheduledThreadPoolExecutor 則是開箱即用的排程執行器。本文深入解析兩者原理與實戰代碼。

方案一:DelayQueue——打造自定義延遲任務隊列

核心介面:Delayed

DelayQueue 是無界阻塞隊列,只能放入實現 Delayed 介面的物件:

public interface Delayed extends Comparable<Delayed> {
    long getDelay(TimeUnit unit); // 返回剩餘延遲時間
}

隊列頭部永遠是「延遲期滿時間最早」的元素。當 getDelay(NANOSECONDS) <= 0 時,元素視為到期可取出。

實戰:DelayedTasker 完整實現

設計一個 DelayedTasker 管理任務隊列,內部類 DelayedTask 同時實現 Delayed 與 Runnable:

public class DelayedTasker implements Runnable {
    private final DelayQueue<DelayedTask> queue = new DelayQueue<>();

    public void addTask(DelayedTask task) { queue.put(task); }
    public void removeTask() { queue.poll(); }

    @Override public void run() {
        while (!queue.isEmpty()) {
            try { queue.take().run(); } // 取出並執行到期任務
            catch (InterruptedException e) { break; }
        }
        System.out.println("Finished DelayedTask");
    }

    public static class DelayedTask implements Delayed, Runnable {
        private static int counter = 0;
        private final int id = counter++;
        private final int delta;      // 延遲秒數
        private final long trigger;   // 觸發時間戳(納秒)

        public DelayedTask(int delayInSeconds) {
            delta = delayInSeconds;
            trigger = System.nanoTime() + TimeUnit.NANOSECONDS.convert(delta, TimeUnit.SECONDS);
        }

        @Override public long getDelay(TimeUnit unit) {
            return unit.convert(trigger - System.nanoTime(), TimeUnit.NANOSECONDS);
        }
        @Override public int compareTo(Delayed o) {
            long diff = trigger - ((DelayedTask)o).trigger;
            return (diff < 0) ? -1 : (diff > 0) ? 1 : 0;
        }
        @Override public void run() { System.out.println(this); }
        @Override public String toString() { return "[" + delta + "s]Task" + id; }
    }

    public static void main(String[] args) {
        ExecutorService exec = Executors.newCachedThreadPool();
        DelayedTasker tasker = new DelayedTasker();
        Random rand = new Random();
        for (int i = 0; i < 10; i++) tasker.addTask(new DelayedTask(rand.nextInt(5)));
        exec.execute(tasker);
        exec.shutdown();
    }
}

輸出範例(按延遲時間排序執行):

[0s]Task 1
[0s]Task 2
[0s]Task 3
[1s]Task 6
[2s]Task 5
[3s]Task 8
[4s]Task 0
[4s]Task 4
[4s]Task 7
[4s]Task 9
Finished DelayedTask

特點:任務邏輯封裝在 DelayedTask.run(),隊列長度無上限,適合「任務型別固定、需自定義排序」的場景。

方案二:ScheduledThreadPoolExecutor——企業級排程器

ScheduledThreadPoolExecutor 繼承自 ThreadPoolExecutor,實現 ScheduledExecutorService,支援一次性延遲執行與週期性執行。

核心方法

  • schedule(Runnable, delay, unit):一次性延遲執行。
  • scheduleAtFixedRate(Runnable, initialDelay, period, unit):固定頻率週期執行。
  • scheduleWithFixedDelay(Runnable, initialDelay, delay, unit):固定延遲週期執行(上次結束到下次開始)。

實戰:ScheduleTasker 封裝

public class ScheduleTasker {
    private final ScheduledThreadPoolExecutor scheduler;
    public ScheduleTasker() { this(10); }
    public ScheduleTasker(int corePoolSize) {
        scheduler = new ScheduledThreadPoolExecutor(corePoolSize);
    }
    public void schedule(Runnable task, long delaySeconds) {
        scheduler.schedule(task, delaySeconds, TimeUnit.SECONDS);
    }
    public void shutdown() { scheduler.shutdown(); }

    public static void main(String[] args) {
        ScheduleTasker tasker = new ScheduleTasker();
        tasker.schedule(() -> System.out.println("[1s]Task 1"), 1);
        tasker.schedule(() -> System.out.println("[2s]Task 2"), 2);
        tasker.schedule(() -> System.out.println("[4s]Task 3"), 4);
        tasker.schedule(() -> System.out.println("[10s]Task 4"), 10);
        tasker.shutdown();
    }
}

輸出:

[1s]Task 1
[2s]Task 2
[4s]Task 3
[10s]Task 4

優勢:線程池管理、異常處理、取消機制、週期執行等開箱即用,生產環境首選。

選型指南

維度DelayQueueScheduledThreadPoolExecutor
適用場景自定義任務隊列、特殊排序邏輯標準定時/週期任務、生產環境
任務邏輯需預先定義在 DelayedTask 中可動態傳入任意 Runnable
線程管理自行管理消費者線程內建線程池,自動調度
週期執行需自行實現原生支援

總結:簡單排程用 ScheduledThreadPoolExecutor;需完全控制隊列行為時用 DelayQueue。

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