java中的延迟队列(DelayQueue)

本文介绍了一种基于Redis实现的延时队列RedisDelayQueue,该队列利用Redis的持久化特性来存储队列中的任务,并通过Leader-Follower模式确保任务的正确执行。适用于如订单过期处理等场景。

问:什么情况下用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

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值