问:什么情况下用DelayQueue
答:比如说订单下单后15分钟过期、要触发一系列的逻辑处理。这时候我们就可以用DelayQueue来完成。
问:实现原理是什么呢?
答:请看代码~~!注:这里用redis来存储队列中的任务。代码是复制 java中 DelayQueue的源码改造的。
package com.coinex.common.concurrent;
import static java.util.concurrent.TimeUnit.NANOSECONDS;
import java.util.AbstractQueue;
import java.util.Collection;
import java.util.Iterator;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.Delayed;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import org.redisson.api.RPriorityQueue;
import org.redisson.api.RedissonClient;
import org.redisson.codec.SerializationCodec;
public class RedisDelayQueue<E extends Delayed> extends AbstractQueue<E>
implements BlockingQueue<E> {
private final transient ReentrantLock lock = new ReentrantLock();
private RPriorityQueue<E> q = null;
private Thread leader = null;
private final Condition available = lock.newCondition();
public RedisDelayQueue (RedissonClient redissonClient) {
SerializationCodec codec = new SerializationCodec();
q = redissonClient.getPriorityQueue("priority"+this.hashCode(),codec);
}
@Override
public E poll() {
return null;
}
@Override
public E peek() {
return null;
}
@Override
public boolean offer(E e) {
final Lock lock = this.lock;
lock.lock();
try {
q.offer(e);
if (q.peek().equals(e)) {
leader = null;
available.signal();
}
return true;
} finally {
lock.unlock();
}
}
@Override
public void put(E e) {
offer(e);
}
@Override
public boolean offer(E e, long timeout, TimeUnit unit) throws InterruptedException {
return offer(e);
}
@Override
public E take() throws InterruptedException {
final Lock lock = this.lock;
lock.lockInterruptibly();
try {
for (;;) {
E first = q.peek();
if (first == null)
available.await();
else {
long delay = first.getDelay(NANOSECONDS);
if (delay <= 0)
return q.poll();
first = null;
if (leader != null)
available.await();
else {
Thread thisThread = Thread.currentThread();
leader = thisThread;
try {
available.awaitNanos(delay);
} finally {
if (leader == thisThread)
leader = null;
}
}
}
}
} finally {
if (leader == null && q.peek() != null)
available.signal();
lock.unlock();
}
}
@Override
public E poll(long timeout, TimeUnit unit) throws InterruptedException {
// TODO Auto-generated method stub
return null;
}
@Override
public int remainingCapacity() {
// TODO Auto-generated method stub
return 0;
}
@Override
public int drainTo(Collection<? super E> c) {
// TODO Auto-generated method stub
return 0;
}
@Override
public int drainTo(Collection<? super E> c, int maxElements) {
// TODO Auto-generated method stub
return 0;
}
@Override
public Iterator<E> iterator() {
// TODO Auto-generated method stub
return null;
}
@Override
public int size() {
// TODO Auto-generated method stub
return 0;
}
}
主要就是看task()方法的实现。这里用到一个模式。就是 Leader-Follower
本文介绍了一种基于Redis实现的延时队列RedisDelayQueue,该队列利用Redis的持久化特性来存储队列中的任务,并通过Leader-Follower模式确保任务的正确执行。适用于如订单过期处理等场景。
3719

被折叠的 条评论
为什么被折叠?



