springboot延时队列

该博客介绍了如何在Spring中使用DelayQueue实现延迟任务调度。通过创建一个线程池,将延迟消息放入DelayQueue,当达到指定时间时执行相应业务操作。在应用关闭时能优雅地中断任务。主要涉及线程池、延迟队列和定时任务的集成应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

延迟队列使用时,相当于在开启一个新的线程,在没有到达指定时间时,这个线程会一直阻塞,直到到了指定时间,队列会释放当前的数据,并继续阻塞到下一个数据

@Component
public class DelayedMessageUtils implements ApplicationRunner {
    //在容器启动时自动执行
    private volatile boolean interrupt;
    @Autowired
    private ThreadPoolExecutor threadPoolExecutor;
    private static Logger logger = LoggerFactory.getLogger(DelayedMessageUtils.class);
    @Override
    public void run(ApplicationArguments args) throws UnknownHostException, InterruptedException {

        DelayQueue<DelayedMessage> delayQueue = ConstConfig.delayQueue;
        List<NoticeInfo> list = noticeService.getDelayMsgList();
        list.stream().forEach(e -> {
            DelayedMessage delayedMessage = new DelayedMessage(e.getId(), e.getTiming().getTime());
            delayQueue.offer(delayedMessage);
        });
        /**
ConstConfig.delayQueue.put(DelayedMessage)
         * 第一步
         * spring启动的时候去数据库拿定时发送且没有发送的数据添加到delayQueue
         * ConstConfig.delayQueue.put(DelayedMessage)
         * 注意这里的数据获取要跟ip来获取,以前是哪个ip添加的数据要用这个ip来发送,避免重复发送
         * 待实现....
         */

        threadPoolExecutor.execute(new Runnable() {
            @SneakyThrows
            @Override
            public void run() {
                while (interrupt == false) {
                    DelayedMessage delayedMessage = ConstConfig.delayQueue.take();
                    //拿到delayedMessage.getDataId()去数据库查询待发送的数据 执行业务操作...
                    Boolean bool = noticeService.sendTiming(delayedMessage.getDataId());
                    if(bool==false){
                        //发送给管理员
                        noticeService.sendAdmin(delayedMessage.getDataId());
                    }
                }
            }
        });
    }

    @Component
    public class Destroy implements DisposableBean {
        @Override
        public void destroy() throws Exception {
            interrupt = true;
            threadPoolExecutor.shutdown();
        }
    }
}

package com.cantaline.noticecenter.vo.delayed;

import lombok.SneakyThrows;

import java.util.concurrent.Delayed;
import java.util.concurrent.TimeUnit;

public class DelayedMessage implements Delayed {
    /**
     * 数据要发送的数据id
     */
    private Long dataId;
    /**
     * 定时发送的时间戳 毫秒
     */
    private Long sendTime;

    //
    public Long getDataId() {
        return this.dataId;
    }

    public Long getSendTime() {
        return this.sendTime;
    }

    public DelayedMessage(Long m, Long time) {
        this.dataId = m;
        this.sendTime = time;
    }

    @SneakyThrows
    @Override
    public long getDelay(TimeUnit unit) {
        return sendTime - System.currentTimeMillis();
    }

    @Override
    public int compareTo(Delayed o) {
        DelayedMessage item = (DelayedMessage) o;
        long diff = this.sendTime - item.sendTime;
        if (diff > 0) {
            return 1;
        }
        return -1;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) {
            return true;
        }
        if (o == null || getClass() != o.getClass()) {
            return false;
        }
        if (getClass() != o.getClass()) {
            return false;
        }
        DelayedMessage other = (DelayedMessage) o;
        if (!dataId.equals(other.dataId)) {
            return false;
        }
        return true;
    }
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值