springBoot之延时队列

1、创建延时队列

package com.example.demo.utils;
import lombok.Data;
import java.util.concurrent.DelayQueue;
/**
 * 延时队列
 * 需要保证队列单例
 */
@Data
public class DelayTaskQueue {
    private static class Holder{
         static DelayQueue<DelayTask> instance = new DelayQueue(); //单例保证队列唯一
    }
    public static DelayQueue<DelayTask> getInstance() {
        return Holder.instance;
    }
}

2、创建消息任务(可根据自己业务来)

package com.example.demo.utils;
import lombok.Data;
import lombok.experimental.Accessors;
import java.util.concurrent.Delayed;
import java.util.concurrent.TimeUnit;
/**
 * 延时任务
 * 需要实现 Delayed 接口 重写getDelay和compareTo指定相应的规则
 */
@Data
@Accessors(chain = true)//链式调用注解
public class DelayTask implements Delayed {
    private String id;
    private Long time;
    private Integer type;
    @Override
    public long getDelay(TimeUnit unit) {
        // 计算该任务距离过期还剩多少时间
        long remaining = time - System.currentTimeMillis();
        return unit.convert(remaining, TimeUnit.MILLISECONDS);
    }
    @Override
    public int compareTo(Delayed o) {
        // 比较、排序:对任务的延时大小进行排序,将延时时间最小的任务放到队列头部
        return (int) (this.getDelay(TimeUnit.MILLISECONDS) - o.getDelay(TimeUnit.MILLISECONDS));
    }
}

3、消息生产者(根据业务需要投递消息进入队列)

package com.example.demo.utils;
import lombok.extern.slf4j.Slf4j;
import java.util.concurrent.DelayQueue;
/**
 * 在需要使用到延时队列的业务进行投递任务(消息)
 */
@Slf4j
public class DelayTaskProducer {
    /**
     *
     * @param id  业务id
     * @param time 消费时间  单位:毫秒
     * @param type 业务类型
     */
    public static void delayTask(String id,Long time,Integer type){
        DelayQueue<DelayTask> delayQueue = DelayTaskQueue.getInstance();//创建队列 1
        DelayTask delayTask = new DelayTask();//创建任务
        delayTask.setId(id)
                .setTime(time)
                .setType(type);
        log.info("=============入延时队列,{}",delayTask);
        boolean offer = delayQueue.offer(delayTask);//任务入队
        if(offer){
            log.info("=============入延时队列成功,{}",delayQueue);
        }else{
            log.info("=============入延时队列失败");
        }
    }
}

4、消息消费者(规定自己相应的业务操作)

package com.example.demo.utils;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;
import java.util.concurrent.DelayQueue;
@Data
@Slf4j
@Component
public class DelayTaskConsumer implements CommandLineRunner {
  /*  @Autowired
    private IProPatMeetingService meetingService;
    @Autowired
    private ParActivityService activityService;*/
    @Override
    public void run(String ...args) throws Exception {
        DelayQueue<DelayTask> delayQueue = DelayTaskQueue.getInstance();//获取同一个put进去任务的队列
        new Thread(() -> {
            while (true) {
                try {
                    // 从延迟队列的头部获取已经过期的消息
                    // 如果暂时没有过期消息或者队列为空,则take()方法会被阻塞,直到有过期的消息为止
                    DelayTask delayTask = delayQueue.take();//阻塞
                    switch (delayTask.getType()) {//判断业务类型,执行对应的业务操作
                        case 1:
                            log.info("====================会议消费,{}",delayTask.getType());
                            //ParMeeting meeting = meetingService.getById(delayTask.getId());
                            //meetingService.pushWxMessageAndMail(meeting,true,null);
                            break;
                        case 2:
                            log.info("====================活动报名消费,{}",delayTask.getType());
                            //ParActivity activityApply = activityService.getById(delayTask.getId());
                            //activityService.pushWxAndMailToActivity(activityApply, PartyActivityPushMessageType.apply_activity_type.getCode());
                            break;
                        case 3:
                            log.info("====================活动开始消费,{}",delayTask.getType());
                            //ParActivity activityStart = activityService.getById(delayTask.getId());
                            //activityService.pushWxAndMailToActivity(activityStart,PartyActivityPushMessageType.activity_start_type.getCode());
                            break;
                        default:
                            log.info("====================未找到消费类型,{}",delayTask.getType());
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }).start();
    }
}

### 配置和使用RocketMQ延迟消息队列 #### 项目配置 ##### 引入依赖 为了在Spring Boot项目中集成RocketMQ并支持延迟消息功能,需引入相应的Maven或Gradle依赖项。确保所使用的版本兼容当前项目的其他组件。 对于Maven项目,在`pom.xml`文件中加入如下依赖: ```xml <dependency> <groupId>org.apache.rocketmq</groupId> <artifactId>rocketmq-spring-boot-starter</artifactId> <version>${rocketmq.version}</version> </dependency> ``` 对于Gradle项目,则应在`build.gradle`里添加: ```groovy implementation 'org.apache.rocketmq:rocketmq-spring-boot-starter:${rocketmqVersion}' ``` ##### 配置RocketMQ 编辑application.properties或者application.yml文件来指定RocketMQ的相关参数,比如NameServer地址等基本信息[^3]。 #### 发送延迟消息 要发送带有特定延迟级别的消息,可利用`RocketMQTemplate`提供的API接口完成操作。具体来说,调用其带参重载版的send()函数即可设置延迟等级,该参数表示的是预定义的时间间隔而非绝对时间戳[^1]。 ```java @Autowired private RocketMQTemplate rocketMQTemplate; public void sendMessageWithDelay(String topic, String tag, Object payload, Integer delayLevel){ Message<?> message = MessageBuilder.withPayload(payload).setHeader(RocketMQHeaders.TAGS, tag).build(); rocketMQTemplate.send(topic, message, 3000L, delayLevel); } ``` 上述代码片段展示了如何构建一条具有标签的消息对象,并将其传递给指定主题的同时指定了超时时间和延迟级别。 #### 测试与验证 确认已正确安装并运行了RocketMQ的服务端组件(Name Server & Broker),之后再尝试启动Spring Boot应用程序来进行实际的功能测试[^2]。可以通过编写单元测试案例或是借助HTTP客户端工具(例如Postman)向暴露出来的RESTful API发起请求以触发消息投递行为[^4]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值