【java】java延迟队列DelayQueue

目录

DelayQueue简介

DelayQueue继承体系

Delayed接口

DelayQueue的基本原理

DelayQueue应用场景

DelayQueue简单示例

场景描述

设计思路

 代码实现

 代码说明


DelayQueue简介

DelayQueue 是 Java 中一个实现延时任务的无界阻塞队列。它是 Java 并发包(java.util.concurrent)的一部分,专门用于在延迟一定时间后才能提取元素的场景。

DelayQueue继承体系

public class DelayQueue<E extends Delayed> extends AbstractQueue<E>
    implements BlockingQueue<E> 

可以看到DelayQueue实现了BlockingQueue接口和Delayed接口。 实现BlockingQueue接口说明支持阻塞和线程安全。
DelayQueue<E extends Delayed> 泛型,表明DelayQueue存储的元素必须继承或者实现Delayed接口。

Delayed接口

package java.util.concurrent;


public interface Delayed extends Comparable<Delayed> {

    /**
     * Returns the remaining delay associated with this object, in the
     * given time unit.
     *
     * @param unit the time unit
     * @return the remaining delay; zero or negative values indicate
     * that the delay has already elapsed
     */
    long getDelay(TimeUnit unit);
}

Delayed 是一个标记接口,要求实现以下方法:

  • getDelay(TimeUnit unit):返回元素还需等待的时间,时间单位由参数 unit 指定。
  • compareTo(Delayed other):Delayed 接口继承了 Comparable 接口,因此实现了该接口的对象可以根据其延迟时间进行比较和排序。这使得 DelayQueue 能够始终将延迟时间最短(即最早到期)的元素放在队列头部

DelayQueue的基本原理

//锁,保证多并发情况下线程安全
private final transient ReentrantLock lock = new ReentrantLock();
//队列
private final PriorityQueue<E> q = new PriorityQueue<E>();

DelayQueue 内部维护了一个基于时间排序的优先队列(PriorityQueue)。每个插入队列的元素都必须实现 Delayed 接口,该接口要求实现 getDelay(TimeUnit unit) 方法,用来指定元素在队列中剩余的延迟时间。当队列的头元素(即优先级最高的元素)延迟时间为零或负数时,才允许被提取。

DelayQueue应用场景

  • 任务调度

    • 在规定时间后执行某些任务,如定时发送消息、定时执行批处理任务。
  • 缓存过期管理

    • 将缓存数据放入 DelayQueue,设置缓存的过期时间,当时间到期后自动删除或处理这些缓存。
  • 限速器

    • 用于限制某些操作的执行频率,例如 API 调用频率控制。

DelayQueue简单示例

场景描述

假设有一个在线购物系统,当用户下单后,如果在30分钟内没有付款,则自动取消订单。为了实现这一功能,可以使用 DelayQueue 结合线程池异步处理,实现延时任务触发。

设计思路

  • 任务:表示订单的延时取消操作
  • 线程池:利用异步执行操作,确保系统可以处理高并发的延时任务
  • DelayQueue:用于管理延时任务,根据任务的延时时间自动触发

 代码实现

import java.util.concurrent.*;

// 定义订单类,实现Delayed接口
class Order implements Delayed {
    private String orderId;
    private long startTime; // 延时时间

    public Order(String orderId, long delayTime) {
        this.orderId = orderId;
        this.startTime = System.currentTimeMillis() + delayTime;
    }

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

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

    public String getOrderId() {
        return orderId;
    }

    public void cancel() {
        System.out.println("Order " + orderId + " is cancelled.");
    }
}

public class DelayedOrderCancellation {
    // 创建线程池和DelayQueue
    private static final ExecutorService executor = Executors.newFixedThreadPool(10);
    private static final DelayQueue<Order> delayQueue = new DelayQueue<>();

    public static void main(String[] args) {
        // 模拟创建订单并添加到DelayQueue中,延时30分钟(30 * 60 * 1000 毫秒)
        Order order1 = new Order("1001", 30 * 60 * 1000);
        delayQueue.put(order1);

        // 启动异步任务处理线程
        executor.execute(() -> {
            while (true) {
                try {
                    // 从DelayQueue中取出已到期的任务
                    Order order = delayQueue.take();
                    order.cancel(); // 取消订单
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                    break;
                }
            }
        });

        // 模拟系统其他业务逻辑...
    }
}

 代码说明

  1. Order类:实现 Delayed 接口,包含订单ID和延时时间。在 getDelay 方法中计算剩余的延时时间,在 compareTo 方法中进行比较。
  2. DelayQueueDelayQueue 是一个无界阻塞队列,用于管理 Delayed 元素。只有到期的元素才能被取出。
  3. 线程池:使用 ExecutorService 来异步处理订单的取消任务,防止主线程阻塞。
  4. 延时任务处理:在 executor 中运行的线程不断从 DelayQueue 中获取到期的订单并执行取消操作。

DelayQueue 为 Java 并发编程提供了强大的延时任务支持,适用于需要时间控制的任务调度场景。 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值