浅谈 DelayQueue 延时队列

 前言:DelayQueue延时队列是阻塞队列中的一种,想了解其他阻塞队列,点击进来学习 BlockingQueue 阻塞队列_程序员大禹的博客-CSDN博客

一、什么是DelayQueue延时队列

是一个支持延时获取元素的无界阻塞队列。队列使用PriorityQueue来实现。队列中的元素必须实现Delayed接口,在创建元素时可以指定多久才能从队列中获取当前元素。只有在延迟期满时才能从队列中提取元素。

二、使用场景

1、用户下订单后,超过一段时间未支付,订单取消

2、停车场停车超时,发送短信通知;

三、代码示例

1、定义延时对象DelayEvent,需要实现Delayed接口。

import org.springframework.stereotype.Component;
import java.util.concurrent.Delayed;
import java.util.concurrent.TimeUnit;

@Component
public class DelayEvent implements java.util.concurrent.Delayed {

    //任务ID
    private int id;
    //数据
    private String data;
    // 插入时间
    private long startTime;
    // 在队列中的保留时间
    private long retainTime;


    public int getId() { return id;}

    public void setId(int id) {
        this.id = id;
    }
    public String getData() {
        return data;
    }

    public void setData(String data) {
        this.data = data;
    }
    public long getStartTime() {
        return startTime;
    }

    public void setStartTime(long startTime) {
        this.startTime = startTime;
    }
    public long getRetainTime() {
        return retainTime;
    }

    public void setRetainTime(long retainTime) {
        this.retainTime = retainTime;
    }


    public DelayEvent() {}

    public DelayEvent(int id, String data, long retainTime) {
        this.id = id;
        this.data = data;
        this.startTime = System.currentTimeMillis();
        this.retainTime = retainTime;
    }

   /**
     * 判定元素是否过期, 过期时间 - 当前时间
     *
     * @param unit
     * @return
     */

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

   /**
     * 确定先后顺序
     *
     * @param o
     * @return
     */
    @Override
    public int compareTo(Delayed o) {
        DelayEvent delayEvent = (DelayEvent) o;
        return (int) (this.getDelay(TimeUnit.MILLISECONDS) - o.getDelay(TimeUnit.MILLISECONDS));
    }


}

2、测试


public class TestMain {

 public static final DelayQueue<DelayEvent> queue = new DelayQueue<DelayEvent>();
    public static void main(String[] args) {

        //创建个线程放入任务到阻塞队列中
        Thread thread = new Thread(() -> {
            DelayEvent delayEvent1 = new DelayEvent(1, "任务1", 1000);
            DelayEvent delayEvent2 = new DelayEvent(2, "任务2", 6000);
            DelayEvent delayEvent3 = new DelayEvent(3, "任务3", 3000);
            DelayEvent delayEvent5 = new DelayEvent(5, "任务5", 5000);

            queue.add(delayEvent1);
            queue.add(delayEvent2);
            queue.add(delayEvent3);
            queue.add(delayEvent5);
        });

        thread.start();

        //从队列中取出数据
        try {
            while (true) {
                if (queue.size() > 0) {
                    DelayEvent event = (DelayEvent) queue.take();
                    String str = JSON.toJSONString(event);
                    System.out.println(str);
                }
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

    }

}

3、执行结果

{"data":"任务1","id":1,"retainTime":1000,"startTime":1651046995180}
{"data":"任务3","id":3,"retainTime":3000,"startTime":1651046995180}
{"data":"任务5","id":5,"retainTime":5000,"startTime":1651046995180}
{"data":"任务2","id":2,"retainTime":6000,"startTime":1651046995180}

四、DelayQueue相关API

变量和类型方法描述
booleanadd​(E e)

将指定的元素插入此延迟队列。

voidclear()

以原子方式从此延迟队列中删除所有元素。

intdrainTo​(Collection<? super E> c)

从此队列中删除所有可用元素,并将它们添加到给定集合中。

intdrainTo​(Collection<? super E> c, int maxElements)

从该队列中删除最多给定数量的可用元素,并将它们添加到给定集合中。

Iterator<E>iterator()

返回此队列中所有元素(已过期和未过期)的迭代器。

booleanoffer​(E e)

将指定的元素插入此延迟队列。

booleanoffer​(E e, long timeout, TimeUnit unit)

将指定的元素插入此延迟队列。

Epeek()

检索但不删除此队列的头部,如果此队列为空,则返回 null 。

Epoll()

检索并删除此队列的头部,如果此队列没有具有过期延迟的元素,则返回 null 。

Epoll​(long timeout, TimeUnit unit)

检索并删除此队列的头部,必要时等待,直到此队列上具有过期延迟的元素或指定的等待时间到期为止。

voidput​(E e)

将指定的元素插入此延迟队列。

intremainingCapacity()

始终返回 Integer.MAX_VALUE因为 DelayQueue不受容量限制。

booleanremove​(Object o)

从此队列中删除指定元素的单个实例(如果存在),无论它是否已过期。

Etake()

检索并删除此队列的头部,必要时等待,直到此队列上有一个具有过期延迟的元素。

Object[]toArray()

返回包含此队列中所有元素的数组。

<T> T[]toArray​(T[] a)

返回包含此队列中所有元素的数组; 返回数组的运行时类型是指定数组的运行时类型。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java中的DelayQueue是一个特殊的队列,它只允许在指定的延迟时间之后才能从队列中取出元素。可以使用DelayQueue来实现一些延迟任务的功能,例如任务调度、缓存过期等。 DelayQueue基于PriorityQueue实现,但是它的元素必须实现Delayed接口,Delayed接口中定义了一个getDelay()方法,返回元素的延迟时间。 当从DelayQueue中取出元素时,如果该元素的延迟时间还没有到达,则该元素会被重新加入队列中,直到延迟时间到达。 以下是一个简单的使用DelayQueue的例子: ```java import java.util.concurrent.DelayQueue; import java.util.concurrent.Delayed; import java.util.concurrent.TimeUnit; public class DelayQueueExample { public static void main(String[] args) throws InterruptedException { DelayQueue<DelayedElement> delayQueue = new DelayQueue<DelayedElement>(); delayQueue.add(new DelayedElement("element1", 2000)); delayQueue.add(new DelayedElement("element2", 5000)); delayQueue.add(new DelayedElement("element3", 1000)); while (!delayQueue.isEmpty()) { DelayedElement element = delayQueue.take(); System.out.println("Taking element: " + element); } } static class DelayedElement implements Delayed { private String name; private long delayTime; public DelayedElement(String name, long delayTime) { this.name = name; this.delayTime = System.currentTimeMillis() + delayTime; } @Override public long getDelay(TimeUnit unit) { long diff = delayTime - System.currentTimeMillis(); return unit.convert(diff, TimeUnit.MILLISECONDS); } @Override public int compareTo(Delayed o) { if (this.delayTime < ((DelayedElement) o).delayTime) { return -1; } if (this.delayTime > ((DelayedElement) o).delayTime) { return 1; } return 0; } @Override public String toString() { return "DelayedElement{" + "name='" + name + '\'' + ", delayTime=" + delayTime + '}'; } } } ``` 在上面的例子中,我们创建了一个DelayQueue,并向其中添加了三个DelayedElement元素。每个元素都有一个延迟时间,分别为2秒、5秒和1秒。 在主线程中,我们不断地从DelayQueue中取出元素,直到队列为空。当元素的延迟时间还没有到达时,它会被重新加入队列中,直到延迟时间到达。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值