大发快三_快三最新网址_大发快三最新网址 - 由大发快三,快三最新网址,大发快三最新网址社主办的《大发快三,快三最新网址,大发快三最新网址》是我国消费领域中一张全国性、全方位、大容量的综合性日报。其立足消费网投领域,依托轻工行业,面向城乡市场,最先发布相关的专业权威资讯。

[转] Java 无界阻塞队列 DelayQueue 入门实战

  • 时间:
  • 浏览:1

原文出处:http://cmsblogs.com/ 『chenssy

DelayQueue是另三个白 支持延时获取元素的无界阻塞队列。顶端的元素完整性总要 “可延期”的元素,列头的元素是最先“到期”的元素,是因为队列顶端那么元素到期,是必须从列头获取元素的,哪怕有元素要是行。也要是说必须在延迟期到时才都都可不都可不可不可以 从队列中取元素。

DelayQueue主要用于另三个白 方面:

  • 缓存:清掉缓存中超时的缓存数据
  • 任务超时正确处理

DelayQueue

DelayQueue实现的关键主要有如下几块:

  1. 可重入锁ReentrantLock
  2. 用于阻塞和通知的Condition对象
  3. 根据Delay时间排序的优先级队列:PriorityQueue
  4. 用于优化阻塞通知的守护多多线程 元素leader

ReentrantLock、Condition这另三个白 对象就不需用阐述了,他是实现整个BlockingQueue的核心。PriorityQueue是另三个白 支持优先级守护多多线程 排序的队列(参考【死磕Java并发】-----J.U.C之阻塞队列:PriorityBlockingQueue),leader顶端阐述。这里大家先来了解Delay,他是实现延时操作的关键。

Delayed

Delayed接口是用来标记那些应该在给定延迟时间之前 执行的对象,它定义了另三个白 long getDelay(TimeUnit unit)法律辦法 ,该法律辦法 返回与此对象相关的的剩余时间。一齐实现该接口的对象需用定义另三个白 compareTo 法律辦法 ,该法律辦法 提供与此接口的 getDelay 法律辦法 一致的排序。

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

咋样使用该接口呢?顶端说的非常清楚了,实现该接口的getDelay()法律辦法 ,一齐定义compareTo()法律辦法 即可。

内控 形态

先看DelayQueue的定义:

    public class DelayQueue<E extends Delayed> extends AbstractQueue<E>
            implements BlockingQueue<E> {
        /** 可重入锁 */
        private final transient ReentrantLock lock = new ReentrantLock();
        /** 支持优先级的BlockingQueue */
        private final PriorityQueue<E> q = new PriorityQueue<E>();
        /** 用于优化阻塞 */
        private Thread leader = null;
        /** Condition */
        private final Condition available = lock.newCondition();

        /**
         * 省略过多代码
         */
    }

看完DelayQueue的内控 形态就对顶端几块关键点一目了然了,就让这里有这个 需用注意,DelayQueue的元素都需用继承Delayed接口。一齐都可不都可不可不可以 必须从这里初步理清楚DelayQueue内控 实现的机制了:以支持优先级无界队列的PriorityQueue作为另三个白 容器,容器顶端的元素都应该实现Delayed接口,在每次往优先级队列中加进元素时以元素的过期时间作为排序条件,最先过期的元素放在优先级最高。

offer()

    public boolean offer(E e) {
        final ReentrantLock lock = this.lock;
        lock.lock();
        try {
            // 向 PriorityQueue中插入元素
            q.offer(e);
            // 是因为当前元素的对首元素(优先级最高),leader设置为空,唤醒所有等待时间守护多多线程


            if (q.peek() == e) {
                leader = null;
                available.signal();
            }
            // 无界队列,永远返回true
            return true;
        } finally {
            lock.unlock();
        }
    }

offer(E e)要是往PriorityQueue中加进元素,具体能必须参考(【死磕Java并发】-----J.U.C之阻塞队列:PriorityBlockingQueue)。整个过程还是比较简单,就让在判断当前元素是与非 为对首元素,是因为是句子则设置leader=null,这是非常关键的另三个白 步骤,顶端阐述。

take()

    public E take() throws InterruptedException {
        final ReentrantLock lock = this.lock;
        lock.lockInterruptibly();
        try {
            for (;;) {
                // 对首元素
                E first = q.peek();
                // 对首为空,阻塞,等待时间off()操作唤醒
                if (first == null)
                    available.await();
                else {
                    // 获取对首元素的超时时间
                    long delay = first.getDelay(NANOSECONDS);
                    // <=0 表示已过期,出对,return
                    if (delay <= 0)
                        return q.poll();
                    first = null; // don't retain ref while waiting
                    // leader != null 证明有这个

守护多多线程


在操作,阻塞
                    if (leader != null)
                        available.await();
                    else {
                        // 就让将leader 设置为当前守护多多线程


,独占
                        Thread thisThread = Thread.currentThread();
                        leader = thisThread;
                        try {
                            // 超时阻塞
                            available.awaitNanos(delay);
                        } finally {
                            // 释放leader
                            if (leader == thisThread)
                                leader = null;
                        }
                    }
                }
            }
        } finally {
            // 唤醒阻塞守护多多线程


            if (leader == null && q.peek() != null)
                available.signal();
            lock.unlock();
        }
    }

首先是获取对首元素,是因为对首元素的延时时间 delay <= 0 ,则能必须出对了,直接return即可。就让设置first = null,这里设置为null的主要目的是为了正确处理内存泄漏。是因为 leader != null 则表示当前有守护多多线程 占用,则阻塞,就让设置leader为当前守护多多线程 ,就让调用awaitNanos()法律辦法 超时等待时间。

first = null

这里为那些是因为不设置first = null,则会引起内存泄漏呢?守护多多线程 A到达,列首元素那么到期,设置leader = 守护多多线程 A,这是守护多多线程 B来了是因为leader != null,则会阻塞,守护多多线程 C一样。我希望守护多多线程 阻塞完毕了,获取列首元素成功,出列。这个 之前 列首元素应该会被回收掉,就让什么的问题是它还被守护多多线程 B、守护多多线程 C持有着,过多不用回收,这里必须另三个白 守护多多线程 ,是因为有守护多多线程 D、守护多多线程 E...呢?要是会无限期的必须回收,就会造成内存泄漏。

这个 入队、出对过程和这个 的阻塞队列那么很大区别,无非是在出对的之前 增加了另三个白 到期时间的判断。一齐通过leader来减少并必须阻塞。

转载,请保留原文地址,谢谢 ~