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

ScheduleThreadPoolExecutor 源碼深度解析:延遲任務與定時調度的核心機制

     編輯:Java 綜合教學

核心組件架構

ScheduledThreadPoolExecutor 繼承 ThreadPoolExecutor,新增兩大關鍵內部類:

  • ScheduledFutureTask<V>:封裝任務、執行時間、週期、序號
  • DelayedWorkQueue:基於最小堆的延遲隊列,堆頂永遠是最早到期任務

ScheduledFutureTask 關鍵屬性

private final long sequenceNumber;  // 入隊順序,保證 FIFO
private long time;                  // 下次執行時間 (nanoTime)
private final long period;          // >0 固定頻率,<0 固定延遲,=0 單次
private int heapIndex;              // 堆中索引,支援 O(1) 移除/更新

關鍵方法解析

getDelay(TimeUnit)

public long getDelay(TimeUnit unit) {
    return unit.convert(time - now(), NANOSECONDS);
}

返回任務距離執行還需等待的時間,供隊列排序與 take() 阻塞使用。

compareTo(Delayed)

public int compareTo(Delayed other) {
    if (other == this) return 0;
    if (other instanceof ScheduledFutureTask) {
        ScheduledFutureTask x = (ScheduledFutureTask) other;
        long diff = time - x.time;
        if (diff < 0) return -1;
        if (diff > 0) return 1;
        return sequenceNumber < x.sequenceNumber ? -1 : 1; // 時間同則按入隊序
    }
    long d = getDelay(NANOSECONDS) - other.getDelay(NANOSECONDS);
    return (d < 0) ? -1 : (d > 0) ? 1 : 0;
}

最小堆比較器:優先按 time,次按 sequenceNumber 保證穩定性。

setNextRunTime()

private void setNextRunTime() {
    long p = period;
    if (p > 0) time += p;                    // 固定頻率:上次執行時間 + 週期
    else time = triggerTime(-p);             // 固定延遲:當前時間 + 延遲
}

triggerTime(long delay)

long triggerTime(long delay) {
    return now() + ((delay < (Long.MAX_VALUE >> 1)) ? delay : overflowFree(delay));
}
private long overflowFree(long delay) {
    Delayed head = (Delayed) super.getQueue().peek();
    if (head != null) {
        long headDelay = head.getDelay(NANOSECONDS);
        if (headDelay < 0 && delay - headDelay < 0) return Long.MAX_VALUE + headDelay;
    }
    return delay;
}

防止 compareTo 中相減溢出:若隊列頭任務已過期(負延遲),新任務延遲不得導致計算溢出。

兩種排程模式差異

模式方法period 符號下次執行時間計算適用場景
固定頻率scheduleAtFixedRate正數上次執行時間 + period心跳、定時掃描
固定延遲scheduleWithFixedDelay負數上次執行結束時間 + |period|任務耗時不定、需間隔

DelayedWorkQueue 亮點

  • 最小堆數組 RunnableScheduledFuture[] queue,初始容量 16,動態擴容。
  • heapIndex 讓 remove() 達到 O(log n) 而非 O(n) 掃描。
  • take() 若堆頂任務未到期,精確 LockSupport.parkNanos(delay) 休眠,避免忙等待。
  • drainTo() 支援批量導出,配合 shutdownNow() 快速清空。

總結

ScheduledThreadPoolExecutor 通過最小堆延遲隊列 + 時間戳驅動 + 週期重算,實現了高效、精準的定時調度。理解 ScheduledFutureTask 的 time/period/sequenceNumber 交互,是掌握其核心的鑰匙。

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