如何实现延迟队列

业务背景

在平时的业务中我们可能会碰到这样的需求,用户A将任务分配给用户B,如果30天后用户B还没有处理这个任务,那么系统自动将这个任务转发给用户C,或者将任务退回给任务A。

这里我们就可以使用延迟队列,我们写好转发方法或者退回方法,用户A分配任务时将时间记录放入延迟队列。当30天后用户B没有处理,我们获取从延迟队列里面获取这个记录,能获取得到,就执行转发方法或退回方法。如果30天内用户B处理了任务,那么就将延迟队列对应的时间记录删掉。

图片

任务转办

当然延迟队列还有很多使用场景,比如用户下单30分钟还没付款,就将订单关闭、外卖平台发送订餐通知,下单成功后60s给用户推送短信等。

Redis实现的延迟队列

我们可以使用Redis的zset可以用于作延迟队列,score为延迟的时间点,获取时顺序获取端口的值,如果当前时间戳等于score则可取出。

图片

至于如何使用Redis做延迟队列,有兴趣的童鞋可以看看我之前下的这篇文章:

[Redis实现延迟队列](Redis实现延迟队列 (qq.com))

Java自带的延迟队列

当然使用Redis做延迟队列并投入生产,其设计还是很复杂的,这里我推荐JDK中的延迟队列API,在java.util.concurrent包下DelayQueue

我们来看看它的使用。

图片

首先我们直接创建一个延迟队列:

// 延迟消息队列
private static DelayQueue delayQueue = new DelayQueue();

系统启动后,我们先后添加两个消息:

public static void producer() {
    // 添加消息
    delayQueue.put(new MyDelay(1000, "消息1"));
    delayQueue.put(new MyDelay(3000, "消息2"));
}

我们再来从延迟队列中获取数据:

public static void consumer() throws InterruptedException {
    System.out.println("开始执行时间:" +
            DateFormat.getDateTimeInstance().format(new Date()));
    while (!delayQueue.isEmpty()) {
        System.out.println(delayQueue.take());
    }
    System.out.println("结束执行时间:" +
            DateFormat.getDateTimeInstance().format(new Date()));
}

测试结果为:

开始执行时间:2020-12-5 13:50:34
消息1
消息2
结束执行时间:2020-12-5 13:50:37

我们看到,消息2在延迟了3s后才从队列中被取出。

关于DelayQueue实际是基于优先队列来实现的。所谓的优先队列,出队是按照优先级来出的,并不是像传统的队列那样先进先出。优先队列底层是二叉堆,关于什么是二叉堆,有兴趣的童鞋可以去网上了解下。

下面是优先队列的示例代码:

实体Student的值:

@AllArgsConstructor
@Data
public class Student {
    private Integer score;
    private String name;
    ...
}

这里我们按照score值从大到小出队。

代码执行结果:

Name:Zhouzhou Level:100
Name:Lvshen Level:80
Name:Hall Level:60

关于其它的方式实现延迟队列

我在网上收集了几种延迟队列的实现方式:

  • 定期轮询(数据库等)

  • DelayQueue(JDK的API)

  • Timer

  • ScheduledExecutorService

  • 时间轮(kafka)

  • RabbitMQ

  • Quartz

  • Redis Zset

  • Koala

  • JCronTab

  • SchedulerX(阿里)

  • 有赞延迟队列

具体实现方式可以看看这篇文章:

你真的了解延时队列吗

好啦今天的文章就到这里啦!如果你的项目中有需要使用延迟队列的地方,希望这篇文章能帮助你。

往期推荐

扫码二维码,获取更多精彩。或微信搜Lvshen_9,可后台回复获取资料

  1. 回复"java" 获取java电子书;

  2. 回复"python"获取python电子书;

  3. 回复"算法"获取算法电子书;

  4. 回复"大数据"获取大数据电子书;

  5. 回复"spring"获取SpringBoot的学习视频。

  6. 回复"面试"获取一线大厂面试资料

  7. 回复"进阶之路"获取Java进阶之路的思维导图

  8. 回复"手册"获取阿里巴巴Java开发手册(嵩山终极版)

  9. 回复"总结"获取Java后端面试经验总结PDF版

  10. 回复"Redis"获取Redis命令手册,和Redis专项面试习题(PDF)

  11. 回复"并发导图"获取Java并发编程思维导图(xmind终极版)

另:点击【我的福利】有更多惊喜哦。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值