思路
通过zset数据结构,将时间戳作为key的分数,存储到redis中
task定时任务,定时获取当前时间戳,然后从redis中获取在分数在到时间戳之间的key的集合
遍历该集合,remove()消费消息
Tash.java
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import java.text.SimpleDateFormat;
import java.util.Iterator;
import java.util.Set;
@Component
public class Task {
@Autowired
RedisTemplate<String,String> redisTemplate;
//TODO 每秒执行一次
@Scheduled(cron = "*/1 * * * * * ")
public void execute(){
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
System.out.println("等待消费中...");
//从redisTemplate中读取知道当前时间戳为止的数据
//这里读出来的是值集合(不是分数)
Set<String> delayedQueue = redisTemplate.opsForZSet().rangeByScore("delayed queue", 0, System.currentTimeMillis());
Iterator<String> iterator = delayedQueue.iterator();
while (iterator.hasNext()){
String key = iterator.next();
Double timestamp = redisTemplate.opsForZSet().score("delayed queue",key);
if(System.currentTimeMillis()>timestamp){
System.out.println("时间到了,消费数据:"+key);
redisTemplate.opsForZSet().remove("delayed queue",key);
}
}
}
}
测试类发送消息 代码
@Autowired
RedisTemplate<String,String> redisTemplate;
@Test
void contextLoads() {
String name = "delayed queue";
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
for (int i = 0; i <= 10; i++) {
Calendar now = Calendar.getInstance();
now.setTime(new Date());
now.set(Calendar.MINUTE,now.get(Calendar.MINUTE)+i);
System.out.println("当前时间:"+simpleDateFormat.format(System.currentTimeMillis()));
System.out.println("消费时间:"+simpleDateFormat.format(now.getTime()));
//第一个getTime()返回的是Date对象,第二个getTime()返回的是时间戳
redisTemplate.opsForZSet().add(name,String.valueOf(i),now.getTime().getTime());
}
}