最近遇到这么一个需求,程序中有一个功能需要发送短信,当满足某些条件后,如果上一步的短信还没有发送出去,那么应该取消这个短信的发送。在翻阅java的api后,发现java中有一个延时队列可以解决这个问题。
实现思路:
1、需要延时发送消息的实体类实现 Delayed 接口,在getDelay方法中,返回这个对象还有多上时间需要执行。
2、将短信类加入到延时队列DelayQueye中
实现效果:
将短信Sms加入到队列中,到了invokedTime后从队列中直接取出执行。
主线程中启动一个子线程,打印当前时间,查看队列中的数据执行的时机是否正确。
delayqueue 的take方法,获取并移除此队列的头部,在可从此队列获得到期延迟的元素之前一直等待(如有必要)
代码如下:
@Slf4j public class DelayTest { @Data @Builder static class Sms implements Delayed { // 执行时间 private long invokedTime; // 需要发出的消息 private String smg; public static Sms build(String msg, int expireTimeSecond) { return Sms.builder().smg(msg).invokedTime(System.nanoTime() + TimeUnit.NANOSECONDS.convert(expireTimeSecond, TimeUnit.SECONDS)).build(); } /** * 返回这个对象剩余的延时时间 * * @param unit * @return */ @Override public long getDelay(TimeUnit unit) { return unit.convert(invokedTime - System.nanoTime(), TimeUnit.NANOSECONDS); } @Override public int compareTo(Delayed o) { if (o == null || !(o instanceof Sms)) return 1; if (o == this) return 0; Sms sms = (Sms) o; if (this.invokedTime > sms.invokedTime) { return 1; } else if (this.invokedTime == sms.invokedTime) { return 0; } else { return -1; } } } public static void main(String[] args) throws InterruptedException { DelayQueue<Sms> queue = new DelayQueue<>(); queue.add(Sms.build("3-hello3", 3)); queue.add(Sms.build("5-hello5", 5)); queue.add(Sms.build("2-hello2", 2)); queue.add(Sms.build("4-hello4", 1)); queue.add(Sms.build("1-hello1", 1)); new Thread(() -> { Executors.newSingleThreadScheduledExecutor().scheduleAtFixedRate(() -> { log.info(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))); }, 0, 1, TimeUnit.SECONDS); }).start(); Sms sms; while (null != (sms = queue.take())) { System.out.println(sms); } } }
执行结果:
相关推荐
JAVA 实现延迟队列的方法是指在 JAVA 中实现延迟队列的方法,即在特定的延迟时间后触发某个事件,这种机制广泛应用于日常开发的场景中,例如用户登录之后5分钟给用户做分类推送、用户多少天未登录给用户做召回推送、...
Java 延时队列的实现方法 延时队列是一种特殊的队列,它可以根据指定的延迟时间来消费队列中的消息。在 Java 中,实现延时队列有多种方式,以下是六种常见的实现方法: 1. DelayQueue 延时队列 DelayQueue 是 ...
DelayQueue 能够保证队列中的对象是有序的,即队头对象的延迟到期时间最长。 DelayQueue 的使用场景非常广泛,如: 1. 订单业务中,下单之后如果三十分钟之内没有付款就自动取消订单。 2. 饿了吗订餐通知中,...
在提供的文件 `delay-queue-node-master` 中,可能是使用 Node.js 编写的 Redis 延时队列实现。通常,这样的实现会包含以下部分: - 初始化 Redis 连接。 - 定义添加任务、获取和处理到期任务、删除任务等方法。 - ...
5. **消息消费**:定义一个`@RabbitListener`注解的消费方法,用于接收并处理延时队列中的消息。这里可以利用Spring的`@ServiceActivator`或`@Bean`定义多个处理策略,通过策略模式选择合适的处理方式。 6. **消费...
在这个"redis延时队列.zip"压缩包中,包含两个Java文件:DelayDataConsumer.java和DelayDataProducer.java,它们分别代表了延时队列的消费者和生产者角色。 首先,我们来了解Redis延时队列的基本原理。Redis本身并...
整个延迟队列由4个部分组成: 1. JobPool用来存放所有Job的元信息。 2. DelayBucket是一组以时间为维度的有序队列,用来存放所有需要延迟的Job(这里只存放Job Id)。 3. Timer负责实时扫描各个Bucket,并将delay...
将整个Redis当做消息池,以kv形式存储消息 使用ZSET做优先队列,按照score维持优先级
多层时间轮,可根据配置的时间轮大小参数以及插入任务的相对时间,动态地创建不同层次的时间轮实例(这里的多层时间轮采用了...引入了延时队列以减少空轮询,将时间轮的推进与任务的提交执行隔离开,提升模型的效率。
该工具使用DeplayQueue延时队列作为软件架构,通过简单的步骤即可完成安装和使用。首先,你需要创建一个实现LsDelayed接口的任务类,并设置任务的名称和执行时间戳。然后,通过CronDelayQueue的init方法初始化任务...
Spring Boot 使用 RabbitMQ 延时队列是指在 Spring Boot 应用程序中使用 RabbitMQ 实现延时队列的功能。延时队列是指消息队列中的一种特殊类型,它可以在指定的时间点触发消息的处理。这种机制可以很好地应用于电商...
当这个延迟时间到达零时,元素才可从队列中取出。在订单自动取消功能中,我们可以创建一个表示订单的类,实现Delayed接口,并设置一个代表订单超时时间的延迟值。 Redis是一个高性能的键值数据库,常用于缓存和消息...
Java延迟队列是一种特殊的队列结构,它允许元素在队列中等待一段时间,然后才能被消费。在Java中,延迟队列是通过 DelayQueue 实现的,Delayed 接口定义了延迟队列的元素必须实现的两个方法:compareTo 和 getDelay...
本篇文章将深入探讨如何使用JmsTemplate来向队列中发送数据,以及相关的核心概念和技术细节。 首先,了解JMS的基本概念是至关重要的。JMS提供两种主要的消息模型:点对点(Point-to-Point,P2P)和发布/订阅...
当消息在业务队列中处理失败,如因异常导致重试次数达到上限,就会变为死信。DLX允许将这些死信重新发布到另一个特定的Exchange,以便进行后续处理。 1. **死信队列定义** DLX是RabbitMQ中处理异常或无效消息的一...
在这个名为"rabbitmq_delayed.zip"的压缩包中,我们看到的是一个使用SpringBoot框架实现的RabbitMQ延时队列功能的示例代码。下面将详细解释RabbitMQ延时队列的工作原理以及如何在SpringBoot应用中进行集成。 延时...
4. **定时器和延时**:Java的`Timer`类或`ScheduledExecutorService`可以用来设定线程在特定时间后执行,这对应于进程在队列中的等待时间。 5. **队列数据结构**:为了实现多级队列,可能需要使用Java的`Queue`接口...
何为延迟队列?顾名思义,延迟队列就是进入该队列的消息会被延迟消费的队列。而一般的队列,消息一旦...如果不使用延迟队列,那么我们只能通过一个轮询扫描程序去完成。这种方案既不优雅,也不方便做成统一的服务便于
* 过期失效问题是指消息队列中的消息超时未消费而被删除。 * 可以通过使用消息队列的超时机制和重试机制来解决延时和过期失效问题。 七、消息队列的架构设计 * 消息队列的架构设计需要考虑系统的可扩展性、可用性...
这在很多场景下都是必要的,例如定时任务、消息队列中的延迟发送、游戏中的定时事件等。在Java中,我们可以使用`java.util.Timer`类或者`java.time`包中的定时器来实现延时任务;在Python中,可以使用`time.sleep()`...