项目中五种延迟队列的实现及优缺点
文章目录
一、基于Java Concurrent包下DelayQueue实现
1.1、优缺点
1.2、实现步骤
1、实现Delayed接口 重写两方法getDelay和compareTo
2、创建资源 借助DelayQueue延迟队列 生产、消费1的实现类
3、分别实现生产者多线程、消费者多线程
4、进行测试验证
1.3、实现代码
PolicyOrder
import org.jetbrains.annotations.NotNull;
import java.io.Serializable;
import java.util.concurrent.Delayed;
import java.util.concurrent.TimeUnit;
/**
* @author :
* @date :Created in 16:53 2022/8/26
* @description :电子保单
一、基于Java Concurrent包下DelayQueue实现
1、实现Delayed接口 重写两方法getDelay和compareTo
2、创建资源 借助DelayQueue延迟队列 生产、消费1的实现类
3、分别实现生产者多线程、消费者多线程
4、进行测试验证
二、基于Quartz实现
缺点:不够及时,具有周期性
三、基于Redis数据类型ZSet实现
1、需要考虑原子性操作 一般结合lua脚本语言操作
四、基于MQ(RabbitMQ)实现
缺点:难度大
五、基于Redission实现
* @version: 1.0
*/
public class PolicyOrder implements Delayed, Serializable {
private String enquiryId;
private long delayTimeMillis;
private long createTimeMillis;
@Override
public long getDelay(@NotNull TimeUnit unit) {
return unit.convert(getEndTimeMillis() - System.currentTimeMillis(), TimeUnit.MILLISECONDS);
}
@Override
public int compareTo(@NotNull Delayed delayed) {
PolicyOrder policyOrder = (PolicyOrder) delayed;
return (int) ((getEndTimeMillis() - policyOrder.getEndTimeMillis()));
}
public void setEnquiryId(String enquiryId) {
this.enquiryId = enquiryId;
}
public void setDelayTimeMillis(long delayTimeMillis) {
this.delayTimeMillis = delayTimeMillis;
}
public void setCreateTimeMillis(long createTimeMillis) {
this.createTimeMillis = createTimeMillis;
}
public PolicyOrder() {
}
public PolicyOrder(String enquiryId, long delayTimeMillis) {
this.enquiryId = enquiryId;
this.delayTimeMillis = delayTimeMillis;
this.createTimeMillis = System.currentTimeMillis();
}
public long getDelayTimeMillis() {
return delayTimeMillis;
}
public long getCreateTimeMillis() {
return createTimeMillis;
}
public long getEndTimeMillis(){
return this.createTimeMillis + this.delayTimeMillis;
}
}
PolicyOrderDelayResource
import com.alibaba.fastjson.JSON;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.concurrent.DelayQueue;
/**
* @author :
* @date :Created in 18:12 2022/8/26
* @description :
* @version: 1.0
*/
public class PolicyOrderDelayResource {
private static Logger logger = LoggerFactory.getLogger(PolicyOrderDelayResource.class);
private DelayQueue<PolicyOrder> delayQueue = new DelayQueue<>();
/**
* 生产者向延迟队列中添加资源
*/
public void produce() {
try {
//TODO 获取真实的订单 获取一条待处理订单(此处是简化版的代码,实际项目中可据实获取待处理订单)
PolicyOrder queueOrder = new PolicyOrder();
// 随便设置一个到期时间(毫秒),实际项目中可据不同场景设置不同的到期时间
queueOrder.setDelayTimeMillis(3000);
delayQueue.put(queueOrder);
} catch (Exception e) {
logger.error("订单生产出现异常", e);
}
}
/**
* 将延迟队列中的订单移除并处理
*/
public void consume() {
try {
PolicyOrder policyOrder = delayQueue.take();
logger.debug("延迟队列消费者处理订单:[{}]", JSON.toJSONString(policyOrder));
//TODO 去做延迟的逻辑
} catch (Exception e) {
logger.error("异常", e);
}
}
}
ConsumerDelayQueueThread
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* @author :
* @date :Created in 18:18 2022/8/26
* @description :
* @version: 1.0
*/
public class ConsumerDelayQueueThread extends Thread {
private Logger logger = LoggerFactory.getLogger(ConsumerDelayQueueThread.class);
private PolicyOrderDelayResource resource;
public ConsumerDelayQueueThread(PolicyOrderDelayResource resource) {
this.resource = resource;
}
public void run() {
logger.info("延迟队列消费者线程启动");
while (true) {
try {
resource.consume();
} catch (Exception e) {
logger.error("延迟队列消费异常", e);
}
}
}
}
ProducerDelayQueueThread
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* @author :
* @date :Created in 18:17 2022/8/26
* @description :
* @version: 1.0
*/
public class ProducerDelayQueueThread extends Thread {
private Logger logger = LoggerFactory.getLogger(ProducerDelayQueueThread.class);
private PolicyOrderDelayResource resource;
public ProducerDelayQueueThread(PolicyOrderDelayResource resource) {
this.resource = resource;
}
public void run() {
logger.info("延迟队列生产者线程启动");
while (true) {
try {
resource.produce();
} catch (Exception e) {
logger.error("延迟队列生产异常", e);
}
}
}
}
PolicyOrderTest
/**
* @author :
* @date :Created in 18:18 2022/8/26
* @description : 电子保单 延迟队列 测试类
* @version: 1.0
*/
public class PolicyOrderTest {
public static void main(String[] args) {
PolicyOrderDelayResource resource = new PolicyOrderDelayResource();
// 创建一个生产者线程
ProducerDelayQueueThread p = new ProducerDelayQueueThread(resource);
// 目前只开启一个生产者线程和一个消费者线程,后续可以改成线程池
ConsumerDelayQueueThread c = new ConsumerDelayQueueThread(resource);
// start 生产者和消费者线程,开始工作
p.start();
c.start();
}
}
二、基于Quartz实现
缺点:不够及时,具有周期性
优点:实现简单,基本每个项目都会有定时任务模块,集成快。
2.1、XML配置文件版
2.1.1、配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<!--自动扫包,后续注入jedis到任务调度类-->
<context:component-scan base-package="com.yanan.health"/>
<!--clearImgJob-->
<!--注册一个定义任务对象-->
<bean id = "clearImgJob" class="com.yanan.health.jobs.ClearImageJob"/>
<!-- 注册JobDetail,作用是负责通过反射调用指定的Job -->
<bean id="clearImgJobDetail" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
<!--注入对象-->
<property name="targetObject" ref="clearImgJob"/>
<!--注入方法-->
<property name="targetMethod" value="clearImageJob"/>
</bean>
<!--注册一个触发器,指定任务触发的时间(间隔)-->
<bean id="ImgTrigger" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
<property name="jobDetail" ref="clearImgJobDetail"/>
<property name="cronExpression">
<!-- 每隔10秒执行一次任务 0/10 * * * * ? -->
<!-- 每隔2分钟执行一次任务 0 0/2 * * * ? -->
<!-- 每天凌晨2点执行一次任务 0 0 2 * * ? -->
<!--<value>0 0 2 * * ?</value>-->
<value>0/10 * * * * ?</value>
</property>
</bean>
<!-- clearOrdersettingJOb -->
<!--注册一个定义任务对象-->
<bean id="clearOrdersettingJob" class="com.yanan.health.jobs.ClearOrdersetting"/>
<!--注册JobDetails,用来负责通过反射嗲用指定的job-->
<bean id="clearOrdersettingJobDetails" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
<property name="targetObject" ref="clearOrdersettingJob"/>
<property name="targetMethod" value="clearOrdersettingJob"/>
</bean>
<bean id="OrdersettingTrigger" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
<property name="jobDetail" ref="clearOrdersettingJobDetails"/>
<!--设置定时时间-->
<property name="cronExpression">
<!-- 每隔10秒执行一次任务 0/10 * * * * ? -->
<!-- 每隔2分钟执行一次任务 0 0/2 * * * ? -->
<!-- 每天凌晨2点执行一次任务 0 0 2 * * ? -->
<value>0/10 * * * * ?</value>
</property>
</bean>
<!--注册一个统一调用工厂,通过这个调度工厂调度任务-->
<bean id="scheduler" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<property name="triggers">
<list>
<ref bean="ImgTrigger"/>
<ref bean="OrdersettingTrigger"/>
</list>
</property>
</bean>
</beans>
2.1.2、定时任务实现类
/**
* @author :
* @date :Created in 2019/11/4
* @description :定时清理图片
* @version: 1.0
*/
@Slf4j
public class ClearImageJob {
@Autowired
private JedisPool jedisPool;
public void clearImageJob(){
log.info("[定时清理图片]开始...");
try (Jedis jedis = jedisPool.getResource()) {
//计算redis两个集合中的差值,得到一个集合 里面存放的是 前面有的后面没有的
Set<String> set = jedis.sdiff(RedisConst.SETMEAL_PIC_RESOURCES, RedisConst.SETMEAL_PIC_DB_RESOURCES);
//遍历set
for (String img : set) {
log.info("[清理垃圾图片]target:{}", img);
//从七牛云删除
QiniuUtils.deleteFileFromQiniu(img);
//从redis中删除
jedis.srem(RedisConst.SETMEAL_PIC_RESOURCES, img);
}
} catch (QiniuException e) {
log.error("[清理垃圾图片异常]",e);
}finally {
log.info("[清理垃圾图片]完成...");
}
}
}
2.2、Springboot配置文件版
2.2.1、quartz配置类
/**
* @author :
* @date :Created in 18:49 2020/8/12
* @description :
* @version: 1.0
*/
@Configuration
public class QuartzConfig {
/**
* 1.创建Job对象
*/
@Bean
public JobDetailFactoryBean startOfDayJobDetailFactoryBean() {
JobDetailFactoryBean factory = new JobDetailFactoryBean();
//关联我们自己的Job类
factory.setJobClass(StartOfDayJob.class);
return factory;
}
/**
* 2.创建Trigger对象
* 简单的Trigger
*/
/**
* Cron Trigger
*/
@Bean
public CronTriggerFactoryBean startOfDayCronTriggerFactoryBean() {
CronTriggerFactoryBean factory = new CronTriggerFactoryBean();
factory.setJobDetail(startOfDayJobDetailFactoryBean().getObject());
//这里涉及到Cron表达式 可以去看我写的Cron表达式!!! 0/10 * * * * ?此处代表每10秒钟 调用一次0 15 10 15 * ?
//0/10 * * * * ?
//0 15 10 15 * ?
//0 15 10 ? * MON-FRI
// factory.setCronExpression("0 15 10 ? * MON-FRI");
factory.setCronExpression("0 0 */1 * * ?");
return factory;
}
/**
* 3.创建Scheduler对象
*/
@Bean
public SchedulerFactoryBean schedulerFactoryBean(MyAdaptableJobFactory myAdaptableJobFactory) {
SchedulerFactoryBean factory = new SchedulerFactoryBean();
//关联trigger
factory.setTriggers(startOfDayCronTriggerFactoryBean().getObject());
factory.setJobFactory(myAdaptableJobFactory);
return factory;
}
}
/**
* @author :
* @date :Created in 19:18 2020/8/12
* @description :
* @version: 1.0
*/
@Component
public class MyAdaptableJobFactory extends AdaptableJobFactory {
//AutowireCapableBeanFactory 可以将一个对象添加到SpringIOC容器中,并且完成该对象注入
@Autowired
private AutowireCapableBeanFactory autowireCapableBeanFactory;
/**
* 该方法需要将实例化的任务对象手动的添加到springIOC容器中并且完成对象的注入
*/
@Override
protected Object createJobInstance(TriggerFiredBundle bundle) throws Exception {
Object obj = super.createJobInstance(bundle);
//将obj对象添加Spring IOC容器中,并完成注入
this.autowireCapableBeanFactory.autowireBean(obj);
return obj;
}
}
2.2.2、定时任务实现类
/**
* @author
* @date :Created in 18:54 2020/8/12
* @description :
* @version: 1.0
*/
@Component
public class StartOfDayJob extends QuartzJobBean {
@Autowired
private ProductDao productDao;
@Autowired
private OrderDao orderDao;
@Override
protected void executeInternal(JobExecutionContext jobExecutionContext) throws JobExecutionException {
// 任务的具体逻辑
/*System.out.println("1");*/
String startTime = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());
System.out.println(startTime + ",定时任务开始执行");
List<Product> productBySku = productDao.findProductBySku(Global.SKU_INSUFFICIENT);
for (Product product : productBySku) {
System.out.println(product.toString());
}
Jedis jedis = null;
try {
jedis = JedisUtils.getJedis();
String jsonCategories = new Gson().toJson(productBySku);
jedis.set("webShop_productSkuInsufficient", jsonCategories);
} catch (Exception e) {
e.printStackTrace();
} finally {
if (jedis != null) {
jedis.close();
}
}
/*String nowDate = new SimpleDateFormat("yyyy-MM-dd").format(new Date());
List<Orders> orderAndBeforeDate = orderDao.findOrderAndBeforeDate(nowDate);
for (Orders orders : orderAndBeforeDate) {
}*/
String endTime = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());
System.out.println(endTime + ",定时任务执行结束");
}
}
三、基于Redis数据类型ZSet实现
1、需要考虑原子性操作 一般结合lua脚本语言操作
3.1、优缺点
3.2、实现代码
import groovy.util.logging.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.slf4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import javax.annotation.PostConstruct;
import java.util.Set;
import java.util.concurrent.Executors;
/**
* @author :YangYaNan
* @date :Created in 16:43 2022/8/30
* @description :
* @version: 1.0
*/
@Slf4j
@Service
public class RedisDelayQueueUtil {
private static final Logger log = org.slf4j.LoggerFactory.getLogger(RedisDelayQueueUtil.class);
private static final long delayTime = 30000;
@Autowired
private StringRedisTemplate redisTemplate;
public void productionQueue(String ruleId){
long expireTime = System.currentTimeMillis() + delayTime;
log.info("延迟队列添加数据ruleId:{},expireTime{}", ruleId, expireTime);
redisTemplate.opsForZSet().add(RedisConstants.BELAY_QUEUE_KEY, ruleId, expireTime);
}
@PostConstruct
public void consumeRuleIdQueue() {
log.info("订单延时队列扫描已启动.....");
Executors.newSingleThreadExecutor().execute(() -> {
while (true) {
//每次最多取出一个
Set<String> ruleIds = redisTemplate.opsForZSet().rangeByScore(RedisConstants.BELAY_QUEUE_KEY, 0, System.currentTimeMillis(),0,1);
// 如果没有需要消费的消息,则间隔一段时间再扫描
if (CollectionUtils.isEmpty(ruleIds)) {
try {
Thread.sleep(1000L);
} catch (InterruptedException e) {
e.printStackTrace();
}
continue;
}
for (String ruleId : ruleIds) {
//如果抢到了就删除
boolean deleteFlag = redisTemplate.opsForZSet().remove(RedisConstants.BELAY_QUEUE_KEY, ruleId) > 0;
if (deleteFlag) {
// TODO 消费规则信息
log.info("订单延时消息已成功消费,ruleId:{},currentTimeMillis:{}", ruleId, System.currentTimeMillis());
}
}
}
});
}
}
四、基于MQ(RabbitMQ)实现
优点: 高效,可以利用rabbitmq的分布式特性轻易的进行横向扩展,消息支持持久化增加了可靠性。
缺点:难度大
4.1、基于RabbitMQ延时插件实现
4.1.1、实现步骤
- 导包
- 配置yml文件
- 配置交换机等信息
- 创建消息队列枚举类、常量类
- 创建发送者、监听者
- 验证
- 扩展关于spring.factories
4.1.2、代码实现
4.1.2.1、导包
'org.springframework:spring-web',
'org.springframework.boot:spring-boot-starter-amqp'
4.1.2.2、配置yml文件
spring:
rabbitmq:
host: ******
port: 5672
virtual-host: ******
username: ******
password: ******
uid: ******
#如果对异步消息需要回调必须设置为true
publisher-confirms: false
listener:
simple:
acknowledge-mode: auto # 消息确认方式,其有三种配置方式,分别是none、manual(手动ack) 和auto(自动ack) 默认auto
retry:
enabled: true
max-attempts: 3
max-interval: 600000 # 重试最大间隔时间10分钟
initial-interval: 600000 # 重试初始间隔时间10分钟
multiplier: 1
default-requeue-rejected: false
4.1.2.3、配置交换机等信息
/**
* RabbitMQ Direct交换机配置类
*/
@Configuration
public class MQDirectConfig {
@Autowired
private RabbitAdmin rabbitAdmin;
/**
* 创建初始化RabbitAdmin对象
*
* @param connectionFactory connectionFactory
* @return rabbitAdmin
*/
@Bean
public RabbitAdmin rabbitAdmin(ConnectionFactory connectionFactory) {
RabbitAdmin rabbitAdmin = new RabbitAdmin(connectionFactory);
rabbitAdmin.setAutoStartup(true);
return rabbitAdmin;
}
/**
* 默认交换机
*
* @return DirectExchange
*/
@Bean
public DirectExchange defaultExchange() {
return new DirectExchange(DIRECT_DEFAULT, true, false);
}
/**
* 延时交换机
*
* @return CustomExchange
*/
@Bean
public CustomExchange delayedExchange() {
Map<String, Object> args = new HashMap<>();
args.put("x-delayed-type", "direct");
return new CustomExchange(DIRECT_DELAYED, "x-delayed-message", true, false, args);
}
/**
* 读取创建交换机和对列
*/
@PostConstruct
public void declareQueueByConfig() {
for (MessageQueueEnum mqBinding : MessageQueueEnum.values()) {
Queue queue = new Queue(mqBinding.getQueueName(), true);
rabbitAdmin.declareQueue(queue);
rabbitAdmin.declareBinding(
BindingBuilder.bind(queue)
.to(mqBinding.isDelayed() ? delayedExchange() : defaultExchange())
.with(mqBinding.getRoutingKey())
.noargs()
);
}
}
}
4.1.2.4、创建消息队列枚举类、常量类
/**
* 消息队列枚举
*/
public enum MessageQueueEnum {
NANMU_USER(QUEUE_NAME_NANMU_USER, ROUTING_KEY_NANMU_USER, true, 5 * 60 * 1000);
// 队列名称
private final String queueName;
// 绑定key
private final String routingKey;
// 是否为延时队列
private final boolean delayed;
// 延时时长(单位:毫秒)
private final long delayTime;
MessageQueueEnum(String queueName, String routingKey) {
this.queueName = queueName;
this.routingKey = routingKey;
this.delayed = false;
this.delayTime = 0;
}
MessageQueueEnum(String queueName, String routingKey, boolean delayed, long delayTime) {
this.queueName = queueName;
this.routingKey = routingKey;
this.delayed = delayed;
this.delayTime = delayTime;
}
public String getQueueName() {
return queueName;
}
public String getRoutingKey() {
return routingKey;
}
public boolean isDelayed() {
return delayed;
}
public long getDelayTime() {
return delayTime;
}
}
public class MQConstants {
/**
* 交换器
*/
public static final String DIRECT_DEFAULT = "direct.default";
public static final String DIRECT_DELAYED = "direct.delayed";
/**
* 队列名称
*/
public static final String QUEUE_NAME_NANMU_USER = "message.queue.nanmu.user";
/**
* routingKey
*/
public static final String ROUTING_KEY_NANMU_USER = "message.routing.nanmu.user";
}
4.1.2.5、创建发送者、监听者
/**
* 消费发送服务
*/
@Slf4j
@Service
@AllArgsConstructor
public class MessageSender {
private RabbitTemplate rabbitTemplate;
/**
* 发送保单下载消息
*/
public void sendNanMuUserMsg(String userId) {
sendMessage(NANMU_USER, userId);
}
/**
* 向队列发送消息
*/
public void sendMessage(MessageQueueEnum queue, String message) {
log.info("MessageSender, sendMessage start, queue:{}, message:{}", queue, message);
try {
rabbitTemplate.convertAndSend(queue.isDelayed() ? DIRECT_DELAYED : DIRECT_DEFAULT,
queue.getRoutingKey(),
message,
msg -> {
if (queue.isDelayed()) {
msg.getMessageProperties().setHeader("x-delay", queue.getDelayTime());
}
return msg;
});
} catch (Exception e) {
log.error("MessageSender, sendMessage fail, queue:{}, message:{}", queue, message);
}
}
}
@Slf4j
@Service
@AllArgsConstructor
public class MessageListener {
private final IUserService userService;
@RabbitHandler
@RabbitListener(queues = QUEUE_NAME_NANMU_USER)
public void userUpdate(String orderNo) {
log.info("MessageListener userUpdate, received message :{}", orderNo);
userService.userUpdate(orderNo);
}
}
五、基于Redission实现方案
5.1、优缺点
优点:集成简单,实现了集群环境下延迟队列。
缺点:随着业务规模的发展,越来越多的延时操作会导致线程数目不断增加,这里可能会有性能影响。另一方面如果某个时间点的数据突增,可能会产生一种情况,实际发送消息的时间比定好的延迟时间会更加久。
5.2、实现代码
/**
* @param <T>
* @author
*/
public interface IDelayQueueService<T> {
/**
* 将消息推入延迟队列,延迟时间以秒为单位
*
* @param data
* @param time
* @param queueName
*/
void offerSeconds(T data, long time, String queueName);
/**
* 将消息推入延迟队列
*
* @param data
* @param time
* @param timeUnit
* @param queueName
*/
void offer(T data, long time, TimeUnit timeUnit, String queueName);
/**
* 取出队列中数据
*
* @param queueName
* @return
* @throws InterruptedException
*/
T take(String queueName) throws InterruptedException;
/**
* 查找阻塞队列
*
* @param queueName
* @return
*/
RBlockingDeque<T> findBlockingQueue(String queueName);
/**
* 查找延时队列
*
* @param queueName
* @return
*/
RDelayedQueue<T> findDelayQueue(String queueName);
/**
* 查找延时队列
*
* @param blockingQueue
* @return
*/
RDelayedQueue<T> findDelayQueue(RBlockingDeque<T> blockingQueue);
/**
* 队列中是否存在这个任务
*
* @param queueName 队列名
* @param t 任务
* @return
*/
boolean contains(String queueName, T t);
/**
* 清除队列中指定元素
*
* @param queueName
* @param t
* @return
*/
boolean remove(String queueName, T t);
}
/**
* @param <T>
* @author
*/
@Service
@AllArgsConstructor
public class DelayQueueServiceImpl<T> implements IDelayQueueService<T> {
private final RedissonClient redissonClient;
@Override
public void offerSeconds(T data, long time, String queueName) {
offer(data, time, TimeUnit.SECONDS, queueName);
}
@Override
public void offer(T data, long time, TimeUnit timeUnit, String queueName) {
findDelayQueue(queueName).offerAsync(data, time < 0 ? 0 : time, timeUnit);
}
@Override
public T take(String queueName) throws InterruptedException {
RBlockingDeque<T> blockingQueue = findBlockingQueue(queueName);
RDelayedQueue<T> delayQueue = findDelayQueue(blockingQueue);
return blockingQueue.take();
}
@Override
public RBlockingDeque<T> findBlockingQueue(String queueName) {
return redissonClient.getBlockingDeque(queueName);
}
@Override
public RDelayedQueue<T> findDelayQueue(String queueName) {
return redissonClient.getDelayedQueue(findBlockingQueue(queueName));
}
@Override
public RDelayedQueue<T> findDelayQueue(RBlockingDeque<T> blockingQueue) {
return redissonClient.getDelayedQueue(blockingQueue);
}
@Override
public boolean contains(String queueName, T t) {
return findDelayQueue(queueName).contains(t);
}
@Override
public boolean remove(String queueName, T t) {
return findDelayQueue(queueName).remove(t);
}
}
e) throws InterruptedException {
RBlockingDeque<T> blockingQueue = findBlockingQueue(queueName);
RDelayedQueue<T> delayQueue = findDelayQueue(blockingQueue);
return blockingQueue.take();
}
@Override
public RBlockingDeque<T> findBlockingQueue(String queueName) {
return redissonClient.getBlockingDeque(queueName);
}
@Override
public RDelayedQueue<T> findDelayQueue(String queueName) {
return redissonClient.getDelayedQueue(findBlockingQueue(queueName));
}
@Override
public RDelayedQueue<T> findDelayQueue(RBlockingDeque<T> blockingQueue) {
return redissonClient.getDelayedQueue(blockingQueue);
}
@Override
public boolean contains(String queueName, T t) {
return findDelayQueue(queueName).contains(t);
}
@Override
public boolean remove(String queueName, T t) {
return findDelayQueue(queueName).remove(t);
}
}