Java 并发工具包-BlockingQueue-DelayQueue

DelayQueue 延时队列,延时一段时间后执行的队列,根据这个特性,可以应用在
1 缓存的生成及自动过期删除
2 任务超时处理

其存储元素必须继承实现Delayed接口

public interface Delayed extends Comparable<Delayed> {
    long getDelay(TimeUnit unit);
}

可见 我们需要实现两个方法
1 getDelay 获取延迟时间
2 compareTo 内部队列的排序

我们先来看下 入队、出队

 public boolean add(E e) {
        return offer(e);
}
public void put(E e) {
        offer(e);
}
 public boolean offer(E e) {
 // 两个作用 
 //1 下面的引用不需要通过this.lock,直接从堆栈获取引用 效率更高
 //2 防止误操作
        final ReentrantLock lock = this.lock;
        //独占锁 线程安全
        lock.lock();
        try {
        //这里的q是PriorityQueue 优先队列 fifo模式 可以看出DelayQueue 使用的是先进先出的模式,将对象放入队列中  这里会调用compareTo进行内部排序
            q.offer(e);
            //获取当前队列最顶队列对象,如果和当前对象相等,说明
            //原先队列为空
            if (q.peek() == e) {
                leader = null;
                //插入成功,通知唤醒
                available.signal();
            }
            return true;
        } finally {
        // 释放锁
            lock.unlock();
        }
    }
//排序方法
  private void siftUpComparable(int k, E x) {
        Comparable<? super E> key = (Comparable<? super E>) x;
        //循环比较,找到比自己大的 break
        while (k > 0) {
            int parent = (k - 1) >>> 1;
            Object e = queue[parent];

            if (key.compareTo((E) e) >= 0)
                break;
            queue[k] = e;
            k = parent;
        }
        queue[k] = key;
    }

主要看的还是offer方法

//
    public E peek() {
        final ReentrantLock lock = this.lock;
        lock.lock();
        try {
            return q.peek();
        } finally {
            lock.unlock();
        }
    }
    public E poll() {
        final ReentrantLock lock = this.lock;
        lock.lock();
        try {
            E first = q.peek();
            //如果还未过期  则返回null
            if (first == null || first.getDelay(NANOSECONDS) > 0)
                return null;
            else//
                return q.poll();
        } finally {
            lock.unlock();
        }
    }
 public E take() throws InterruptedException {
        final ReentrantLock lock = this.lock;
        //独占锁,可被打断,抛出异常
        lock.lockInterruptibly();
        try {
        //循环执行
            for (;;) {
            //获取当前首个对象
                E first = q.peek();
                //如果为空 说明队列为空,则进行等待 直到有对象入队唤醒
                if (first == null)
                    available.await();
                else {
                //获取需要等待时间 微妙单位
                    long delay = first.getDelay(NANOSECONDS);
                    //如果小于0,已经过时,直接抛出对象返回
                    if (delay <= 0)
                        return q.poll();
                        //对象回收
                    first = null; // don't retain ref while waiting
                    //如果当前leader已经被某线程赋值,则等待
                    if (leader != null)
                        available.await();
                    else {
                        Thread thisThread = Thread.currentThread();
                        //否则赋值leader
                        leader = thisThread;
                        try {
                            //等待delay时间后 唤醒 继续循环
                            available.awaitNanos(delay);
                        } finally {
                        //leader=null 
                            if (leader == thisThread)
                                leader = null;
                        }
                    }
                }
            }
        } finally {
            //当队列不为空,则进行通知,否则不通知
            if (leader == null && q.peek() != null)
                available.signal();
            lock.unlock();
        }
    }
    //he 
     public E poll(long timeout, TimeUnit unit) throws InterruptedException {
        long nanos = unit.toNanos(timeout);
        final ReentrantLock lock = this.lock;
        lock.lockInterruptibly();
        try {
            for (;;) {
                E first = q.peek();
                if (first == null) {
                    if (nanos <= 0)
                        return null;
                    else
                        nanos = available.awaitNanos(nanos);
                } else {
                    long delay = first.getDelay(NANOSECONDS);
                    if (delay <= 0)
                        return q.poll();
                    if (nanos <= 0)
                        return null;
                    first = null; // don't retain ref while waiting
                    if (nanos < delay || leader != null)
                        nanos = available.awaitNanos(nanos);
                    else {
                        Thread thisThread = Thread.currentThread();
                        leader = thisThread;
                        try {
                            long timeLeft = available.awaitNanos(delay);
                            nanos -= delay - timeLeft;
                        } finally {
                            if (leader == thisThread)
                                leader = null;
                        }
                    }
                }
            }
        } finally {
            if (leader == null && q.peek() != null)
                available.signal();
            lock.unlock();
        }
    }

tack 方法貌似多点,不过整过过程还是比较简单的!
1 循环
2 判断是否过时
3 等待

    public final long awaitNanos(long nanosTimeout)
                throws InterruptedException {
                //线程是否被打断  打断 则抛异常,这里和lock.lockInterruptibly();对应
            if (Thread.interrupted())
                throw new InterruptedException();
                //通过当前线程 创建节点
            Node node = addConditionWaiter();
            //尝试是否,并且获取当前状态
            int savedState = fullyRelease(node);
            //过期时间
            final long deadline = System.nanoTime() + nanosTimeout;
            int interruptMode = 0;
            //判断是否需要等待
            while (!isOnSyncQueue(node)) {

                if (nanosTimeout <= 0L) {
                    //插到队列末尾
                    transferAfterCancelledWait(node);
                    break;
                }

                if (nanosTimeout >= spinForTimeoutThreshold)
                //调用底层 对该线程进行阻塞
                    LockSupport.parkNanos(this, nanosTimeout);
                    //是否打断
                if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)
                    break;

                nanosTimeout = deadline - System.nanoTime();
            }
            if (acquireQueued(node, savedState) && interruptMode != THROW_IE)
                interruptMode = REINTERRUPT;
            if (node.nextWaiter != null)
                unlinkCancelledWaiters();
            if (interruptMode != 0)
                reportInterruptAfterWait(interruptMode);
            return deadline - System.nanoTime();
        }

总结

适用于一段时间后执行的场景,常见于自定义缓存、超时、某段时间后需要处理的业务。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值