Java DelayQueue 延遲隊列

Java DelayQueue 延遲隊列

1. DelayQueue 概述

DelayQueue 是 Java 并發包(java.util.concurrent)中的一個 無界 阻塞隊列,用于存儲實現了 Delayed 接口的元素。隊列中的元素只有在達到指定的延遲時間后才能被獲取。

2. DelayQueue 的底層數據結構

DelayQueue 的底層數據結構是 優先級隊列(PriorityQueue),它是一個小頂堆(最小堆),根據元素的過期時間進行排序。

  • 底層采用 PriorityQueue(基于堆的實現)
  • 按照到期時間升序排列,即最早過期的元素在堆頂
  • 元素未過期時,take() 方法會阻塞
  • 支持多線程并發訪問

3. DelayQueue 的實現原理

  • 元素需實現 Delayed 接口,重寫 getDelay() 方法,返回剩余的延遲時間

  • DelayQueue 內部維護一個 PriorityQueue<Delayed>

  • 插入元素時,按照到期時間排序,最早到期的元素位于堆頂。

  • take()
    

    方法獲取堆頂元素:

    • 若到期,直接返回該元素。
    • 若未到期,線程阻塞,直到該元素可用。
    • 使用鎖 + 條件變量ReentrantLock + Condition)控制并發訪問。

4. DelayQueue 的應用場景

DelayQueue 適用于 延遲執行、定時任務、緩存超時管理 等場景,包括:

  • 任務調度(如延遲執行任務、重試機制)
  • 定時消息隊列(如 Kafka 里的延時消息)
  • 訂單超時取消(未支付訂單自動取消)
  • 緩存自動過期(定期清除緩存)
  • 連接超時管理(網絡連接的超時處理)

5. DelayQueue 的優缺點

優點

  • 高效的時間管理,自動處理過期元素
  • 線程安全,內部使用 ReentrantLock 保證并發安全
  • 無界隊列,但受內存限制
  • 阻塞機制,減少 CPU 輪詢

缺點

  • 不支持元素移除(除非手動遍歷 remove()
  • 不能提前獲取未到期元素poll() 只返回到期元素)
  • 無上限(可能導致 OOM)

6. DelayQueue 的替代方案

需求替代方案
需要定時任務ScheduledThreadPoolExecutor
需要分布式延遲隊列Redis ZSet(基于時間戳排序)
高吞吐延遲消息隊列Kafka + 延遲插件
低延遲任務調度TimeWheel(時間輪算法,如 Netty 的 HashedWheelTimer)

7. DelayQueue 使用示例

(1) 定義延遲元素

import java.util.concurrent.Delayed;
import java.util.concurrent.TimeUnit;class DelayedTask implements Delayed {private final long delayTime; // 延遲時間private final long expireTime; // 過期時間private final String name;public DelayedTask(String name, long delay, TimeUnit unit) {this.name = name;this.delayTime = TimeUnit.MILLISECONDS.convert(delay, unit);this.expireTime = System.currentTimeMillis() + this.delayTime;}@Overridepublic long getDelay(TimeUnit unit) {return unit.convert(expireTime - System.currentTimeMillis(), TimeUnit.MILLISECONDS);}@Overridepublic int compareTo(Delayed o) {return Long.compare(this.getDelay(TimeUnit.MILLISECONDS), o.getDelay(TimeUnit.MILLISECONDS));}@Overridepublic String toString() {return "Task{" + "name='" + name + '\'' + ", expireTime=" + expireTime + '}';}
}

(2) 使用 DelayQueue

import java.util.concurrent.DelayQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;public class DelayQueueExample {public static void main(String[] args) {DelayQueue<DelayedTask> queue = new DelayQueue<>();queue.add(new DelayedTask("Task1", 3, TimeUnit.SECONDS));queue.add(new DelayedTask("Task2", 1, TimeUnit.SECONDS));queue.add(new DelayedTask("Task3", 5, TimeUnit.SECONDS));ExecutorService executor = Executors.newSingleThreadExecutor();executor.submit(() -> {while (!queue.isEmpty()) {try {DelayedTask task = queue.take(); // 阻塞獲取到期任務System.out.println("Executing: " + task);} catch (InterruptedException e) {Thread.currentThread().interrupt();}}});executor.shutdown();}
}

(3) 運行結果

Executing: Task{name='Task2', expireTime=...}  // 1s 后執行
Executing: Task{name='Task1', expireTime=...}  // 3s 后執行
Executing: Task{name='Task3', expireTime=...}  // 5s 后執行

8. 總結

  • DelayQueue 是基于優先級隊列的小頂堆實現的阻塞隊列
  • 元素需實現 Delayed 接口,getDelay() 返回剩余時間。
  • 適用于 延遲任務調度、緩存過期管理、訂單超時 等場景。
  • 主要優點是 線程安全、自動延遲控制,缺點是 無法主動獲取未到期元素
  • 可用 ScheduledThreadPoolExecutor、Redis ZSet、Kafka 延時隊列 作為替代方案。

分布式微服務架構下,能使用DelayQueue嗎?

分布式微服務架構 下,不推薦直接使用 DelayQueue,主要原因如下:

1. DelayQueue 的局限性

  • 單機限制DelayQueueJVM 內存隊列,它運行在單個進程,無法在多個微服務實例間共享數據,不能保證高可用性和擴展性
  • 數據丟失風險:若微服務實例崩潰或重啟,DelayQueue 中的任務會丟失,缺乏持久化機制。
  • 無水平擴展能力:隨著流量增長,多個實例無法共享隊列,容易成為瓶頸。

2. 適用于 DelayQueue 的場景

盡管 DelayQueue 不能直接用于分布式架構,但在單機任務調度、短時間小規模的延遲任務場景下仍然可行,例如:

  • 同一個微服務實例內的短期任務(如 1-10 秒級的延遲任務)
  • 不需要高可靠性的本地任務(如定期緩存清理)
  • 沒有跨實例同步要求的任務(如本地事件延遲處理)

3. 分布式替代方案

若要在分布式微服務架構中實現可擴展、高可用的延遲任務調度,可以采用以下方案:

(1) Redis ZSet(有序集合)+ 定時輪詢
  • 原理:利用 Redis 的 ZSet(有序集合),按照 score 存儲任務的執行時間戳,每隔 N 毫秒 輪詢一次取出到期任務執行。

  • 優勢:

    • 支持 分布式部署,多個實例可共享數據
    • 持久化,即使服務重啟,任務仍然存在
    • 高性能,Redis 讀寫性能優越
  • 示例:

    jedis.zadd("delayQueue", System.currentTimeMillis() + 5000, "order:123"); // 5s 后執行
    Set<String> tasks = jedis.zrangeByScore("delayQueue", 0, System.currentTimeMillis());
    if (!tasks.isEmpty()) {tasks.forEach(task -> {process(task); // 處理任務jedis.zrem("delayQueue", task); // 移除已處理任務});
    }
    
  • 適用場景:

    • 訂單超時處理
    • 定時消息推送
    • 低吞吐的延遲任務(如秒級延遲)
(2) Kafka + 延遲隊列插件
  • 原理:Kafka 通過 Kafka Streams延遲隊列插件(如 Kafka Delay Message)支持延遲消費消息。
  • 適用場景:
    • 高吞吐的延遲任務
    • 可靠的分布式消息隊列
  • 缺點:
    • 依賴 Kafka,適用于 需要消息隊列的業務
(3) RabbitMQ/ActiveMQ TTL + 死信隊列
  • 原理:RabbitMQ 支持 TTL(Time-To-Live) 設置,消息超時后自動進入 DLX(Dead Letter Exchange, 死信隊列),可用 消費者監聽 處理。

  • 適用場景:

    • 需要可靠消息隊列
    • 需要高吞吐延遲任務
  • 示例:

    channel.queueDeclare("delayQueue", true, false, false, Map.of("x-message-ttl", 5000));
    channel.basicPublish("", "delayQueue", MessageProperties.PERSISTENT_TEXT_PLAIN, "Delayed Message".getBytes());
    
  • 缺點:

    • 依賴消息中間件,適用于 消息驅動的系統
(4) 分布式任務調度框架
  • 常見框架:
    • XXL-JOB(輕量級,適用于小規模定時任務)
    • Elastic-Job(基于 Zookeeper,適用于高并發調度)
    • Quartz + DB 持久化(適用于復雜定時任務)
  • 適用場景:
    • 定時任務執行
    • 任務分片調度
    • 可持久化任務隊列

4. 結論

建議:如果是 單機應用,可以使用 DelayQueue;如果是 分布式微服務架構,建議使用 Redis ZSet / Kafka / RabbitMQ / 任務調度框架 實現延遲任務。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/72880.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/72880.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/72880.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

LeetCode 解題思路 22(Hot 100)

解題思路&#xff1a; 遞歸思路&#xff1a; 傳入當前節點的最小值和最大值&#xff0c;遞歸判斷左右子樹。結束條件&#xff1a; 當前節點為空或不滿足二叉搜索樹。 Java代碼&#xff1a; class Solution {public boolean isValidBST(TreeNode root) {return isValidBST(ro…

樂享數科:政策助推假日經濟,2月普惠金融-景氣指數穩中有升

數據顯示&#xff0c;2025年2月普惠金融-景氣指數達48.99點&#xff0c;較1月上升0.03點。 企業運行持續向好&#xff0c;企業信心預期和經營活力回升。“假日經濟”與“政策效應”相互疊加&#xff0c;市場供求格局有所改善&#xff0c;景氣水平穩步恢復。 普惠金融-景氣指數…

leetcode日記(108)驗證回文串

看上去很簡單&#xff0c;其實很麻煩。 一開始寫的遞歸&#xff0c;但是內存超限……搜了下發現原因是每次遞歸調用都會創建一個新的字符串副本&#xff0c;這在處理長字符串時會占用大量內存。 class Solution { public:bool isPalindrome(string s) {if(s.size()0||s.size(…

用css繪制收銀鍵盤

最近需求說需要自己弄個收銀鍵盤&#xff0c;于是乎直接上手搓 主要基于Vue3寫的&#xff0c;主要是CSS <template><view class"container"><view class"info"><image class"img" src"" mode"">&l…

智能車間管理系統(源碼+文檔+講解+演示)

引言 在現代制造業中&#xff0c;智能車間管理系統正成為推動工業4.0和智能制造的關鍵力量。它通過整合先進的信息技術和自動化技術&#xff0c;優化生產流程&#xff0c;提高生產效率&#xff0c;降低成本&#xff0c;并確保產品質量。 系統概述 智能車間管理系統采用前后端…

Model Context Protocol - Prompts

1. 概述 Model Context Protocol (MCP) 提供了一種標準化的方式&#xff0c;使服務器能夠向客戶端暴露提示模板&#xff08;prompts&#xff09;。Prompts 是服務器提供的結構化消息和指令&#xff0c;用于與語言模型進行交互。客戶端可以發現可用的提示、獲取其內容&#xff…

辦公自動化:使用 Python 生成 Word 文件:自動生成數據庫文檔 Word 文件

簡簡單單 Online zuozuo :本心、輸入輸出、結果 文章目錄 辦公自動化:使用 Python 生成 Word 文件:自動生成數據庫文檔 Word 文件前言一、環境準備二、編寫代碼三、編寫 Word 模版文件接收數據四、運行代碼,生成文件,大功告成五、說明辦公自動化:使用 Python 生成 Word 文…

嵌入式GPRS協議面試題及參考答案

目錄 GPRS 的全稱是什么?簡述其核心設計目標。 GPRS 中 DNS 服務器的核心作用是什么? BTS 在 EDGE 升級時需要哪些硬件調整? GPRS 的時隙分配策略如何影響多用戶并發? 解釋 PDCH(分組數據信道)的動態分配機制。 如何判斷天饋接反或鴛鴦線問題? GPRS 的 RLC/MAC 層…

Docker 內部通信(網絡)

1. 創建自定義橋接網絡 首先&#xff0c;創建一個自定義的Docker網絡。這可以通過docker network create命令完成。例如&#xff0c;我們可以創建一個名為my_custom_network的網絡&#xff1a; docker network create --driver bridge my_custom_network2. 啟動容器并連接到自…

單片機開發資源分析的實戰——以STM32F103C8T6為例子的單片機資源分析

目錄 第一點&#xff1a;為什么叫STM32F103C8T6 從資源手冊拿到我們的對STM32F103C8T6的資源描述 第二件事情&#xff0c;關心我們的GPIO引腳輸出 第三件事情&#xff1a;去找對應外設的說明部分 前言 本文章隸屬于項目&#xff1a; Charliechen114514/BetterATK: This is…

貪心算法(9)(java)最優除法

題目&#xff1a; 給定一正整數數組 nums,nums中的相鄰整數將進行浮點除法。例如&#xff0c;[2,3.4]->2/3/4. 例如&#xff0c;nums [2,3,4]&#xff0c;我們將求表達式的值“2/3/4"。 但是&#xff0c;你可以在任意位置添加任意數目的括號&#xff0c;來改變算…

騰訊云MySQL數據庫架構分析與使用場景

TDSQL-C for MySQL TDSQL-C MySQL 版&#xff08;TDSQL-C for MySQL&#xff09;是騰訊云自研的新一代云原生關系型數據庫。融合了傳統數據庫、云計算與新硬件技術的優勢&#xff0c;為用戶提供具備高彈性、高性能、海量存儲、安全可靠的數據庫服務。TDSQL-C MySQL 版100%兼容…

榮耀手機卸載應用商店、快應用中心等系統自帶的

1.下載abd ADB Download - Get the latest version of ADB and fastboot 2.手機打開開發者選項 3.手機接電腦打開USB調試 4.下載MT管理器查看系統包名 D:\1.LFD\ADB\platform-tools-latest-windows\platform-tools>adb shell adb.exe: no devices/emulators found 這邊是…

星型拓撲網絡發生網絡風暴

在星型拓撲網絡中&#xff0c;所有的設備&#xff08;如計算機、打印機等&#xff09;通過一個中心設備&#xff08;通常是交換機或集線器&#xff09;連接在一起。 星型拓撲網絡中發生網絡風暴時的情況&#xff1a; 網絡風暴的表現 1.廣播風暴&#xff1a;在星型拓撲中&…

網絡流基本概念及實現算法

基本概念 流網絡 對于一個有向圖, 抽象成水管里的水的模型, 每根管子有容量限制, 計為 G ( V , E ) G (V, E) G(V,E), 首先不考慮反向邊 對于任意無向圖, 都可以將反向邊轉化為上述形式 如果一條邊不存在, 定義為容量為 0 0 0, 形式上來說就是 c ( u , v ) 0 c(u, v) 0 c(…

【css酷炫效果】純CSS實現球形陰影效果

【css酷炫效果】純CSS實現球形陰影效果 緣創作背景html結構css樣式完整代碼基礎版進階版(動態版) 效果圖 想直接拿走的老板&#xff0c;鏈接放在這里&#xff1a;上傳后更新 緣 創作隨緣&#xff0c;不定時更新。 創作背景 剛看到csdn出活動了&#xff0c;趕時間&#xff0…

Linux如何在設備樹中表示和引用設備信息

DTS基本知識 dts 硬件的相應信息都會寫在.dts為后綴的文件中&#xff0c;每一款硬件可以單獨寫一份xxxx.dts&#xff0c;一般在Linux源碼中存在大量的dts文件&#xff0c;對于arm架構可以在arch/arm/boot/dts找到相應的dts&#xff0c;一個dts文件對應一個ARM的machie。 dtsi 值…

【數學建模】模糊綜合評價模型詳解、模糊集合論簡介

模糊綜合評價模型詳解 文章目錄 模糊綜合評價模型詳解1. 模糊綜合評價模型概述2. 模糊綜合評價的基本原理2.1 基本概念2.2 評價步驟 3. 模糊綜合評價的數學模型3.1 數學表達3.2 模糊合成運算 4. 模糊綜合評價的應用領域5. 模糊綜合評價的優缺點5.1 優點5.2 缺點 6. 模糊綜合評價…

C++20 中的同步輸出流:`std::basic_osyncstream` 深入解析與應用實踐

文章目錄 一、std::basic_osyncstream 的背景與動機二、std::basic_osyncstream 的基本原理三、std::basic_osyncstream 的使用方法&#xff08;一&#xff09;基本用法&#xff08;二&#xff09;多線程環境下的使用&#xff08;三&#xff09;與文件流的結合 四、std::basic_…

C/C++藍橋杯算法真題打卡(Day8)

一、P8780 [藍橋杯 2022 省 B] 刷題統計 - 洛谷 算法代碼&#xff1a; #include<bits/stdc.h> // 包含標準庫中的所有頭文件&#xff0c;方便使用各種數據結構和算法 using namespace std; // 使用標準命名空間&#xff0c;避免每次調用標準庫函數時都要加 std::in…