java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > Java DelayQueue延迟队列

Java实现DelayQueue延迟队列示例代码

作者:宋发元

Java中的DelayQueue是一个特殊的队列,它只允许在指定的延迟时间之后才能从队列中取出元素,这篇文章主要给大家介绍了关于Java实现DelayQueue延迟队列的相关资料,需要的朋友可以参考下

JavaDelayQueue延迟队列

1.DelayQueue概述

DelayQueue 是 Java 并发包(java.util.concurrent)中的一个 无界 阻塞队列,用于存储实现了 Delayed 接口的元素。队列中的元素只有在达到指定的延迟时间后才能被获取。

2.DelayQueue的底层数据结构

DelayQueue 的底层数据结构是 优先级队列(PriorityQueue),它是一个小顶堆(最小堆),根据元素的过期时间进行排序。

3.DelayQueue的实现原理

4.DelayQueue的应用场景

DelayQueue 适用于 延迟执行、定时任务、缓存超时管理 等场景,包括:

5.DelayQueue的优缺点

优点

缺点

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;
    }

    @Override
    public long getDelay(TimeUnit unit) {
        return unit.convert(expireTime - System.currentTimeMillis(), TimeUnit.MILLISECONDS);
    }

    @Override
    public int compareTo(Delayed o) {
        return Long.compare(this.getDelay(TimeUnit.MILLISECONDS), o.getDelay(TimeUnit.MILLISECONDS));
    }

    @Override
    public 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吗?

分布式微服务架构 下,不推荐直接使用 DelayQueue,主要原因如下:

1.DelayQueue的局限性

2. 适用于DelayQueue的场景

尽管 DelayQueue 不能直接用于分布式架构,但在单机任务调度、短时间小规模的延迟任务场景下仍然可行,例如:

3. 分布式替代方案

若要在分布式微服务架构中实现可扩展、高可用的延迟任务调度,可以采用以下方案:

(1) Redis ZSet(有序集合)+ 定时轮询

(2) Kafka + 延迟队列插件

(3) RabbitMQ/ActiveMQ TTL + 死信队列

(4) 分布式任务调度框架

4. 结论

建议:如果是 单机应用,可以使用 DelayQueue;如果是 分布式微服务架构,建议使用 Redis ZSet / Kafka / RabbitMQ / 任务调度框架 实现延迟任务。

到此这篇关于Java实现DelayQueue延迟队列的文章就介绍到这了,更多相关Java DelayQueue延迟队列内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文