主要原因是有些人的代码是按照下面这种写法,最主要造成的原因这个写法并不能给你初始化延迟队列,没有初始化延迟队列,就不会接收到延迟队列的数据。
public void addDelay(Object o) {
RBlockingQueue<CallDTO> blockingFairQueue = redissonClient.getBlockingQueue("delay_queue_call");
RDelayedQueue<CallDTO> delayedQueue = redissonClient.getDelayedQueue(blockingFairQueue);
delayedQueue.offer(o, 5, TimeUnit.SECONDS);
}
正确的写法是 这个代码应该放在另外的地方,要不就是在对应的类的构造函数里面进行初始化,要不就通过@bean的方式注入到容器中,也是初始化。
RBlockingQueue<CallDTO> blockingFairQueue = redissonClient.getBlockingQueue("delay_queue_call");
RDelayedQueue<CallDTO> delayedQueue = redissonClient.getDelayedQueue(blockingFairQueue);
源码-稍微写一下大概的思路,具体的可以自己去看源码:
在org.redisson.RedissonDelayedQueue#RedissonDelayedQueue里面有一个初始化任务,这个任务就是查询已经到时间的zset的元素,丢到阻塞队列表面去, 在下面的一行代码里面。
queueTransferService.schedule(queueName, task);
在下面的这个方法里面启动的。
public void start() {
RTopic schedulerTopic = getTopic();
// 这要是这个地方,监听到状态的变更会执行初始化任务
statusListenerId = schedulerTopic.addListener(new BaseStatusListener() {
@Override
public void onSubscribe(String channel) {
pushTask();
}
});
// 这里是监听到新的延迟队列任务的时候会执行任务。
messageListenerId = schedulerTopic.addListener(Long.class, new MessageListener<Long>() {
@Override
public void onMessage(CharSequence channel, Long startTime) {
scheduleTask(startTime);
}
});
}