如果不想在世界上虚度一生,那就要学习一辈子。 延迟元素的无边界阻塞队列,在该队列中,仅当元素的延迟到期时才可以使用它. 此类是Java Collections Framework的成员. 锁 PriorityQueue队列里的元素会根据某些属性排列先后的顺序,这里正好可以利用Delayed接口里的getDelay的返回值来进行排序,delayQueue其实就是在每次往优先级队列中添加元素,然后以元素的delay/过期值作为排序的因素,以此来达到先过期的元素会拍在队首,每次从队列里取出来都是最先要过期的元素 指定用于等待队首元素的线程。 Leader-Follower模式的变体用于最大程度地减少不必要的定时等待.当一个线程成为leader时,它仅等待下一个延迟过去,但是其他线程将无限期地等待.leader线程必须在从take()或poll(…)返回之前向其他线程发出信号,除非其他线程成为过渡期间的leader。.每当队首被具有更早到期时间的元素替换时,leader字段都会被重置为null来无效,并且会发出一些等待线程(但不一定是当前leader)的信号。 因此,等待线程必须准备好在等待时获得并失去leader能力. 当更新的元素在队首变得可用或新的线程可能需要成为 leader 时,会发出条件信号 先看看继承自 BlockingQueue 的方法 1.加锁 其内部调用的是 PriorityQueue 的 offer 方法 将指定的元素插入此优先级队列. 检索并删除此队列的头,如有必要,请等待直到延迟过期的元素在此队列上可用 take 方法是会无限阻塞,直到队头的过期时间到了才会返回. leader 是一个Thread元素,表示当前获取到锁的消费者线程. 若 leader 非 null,说明已有消费者线程获取锁,直接阻塞当前线程. 若 leader 为 null,把当前线程赋给 leader,并等待剩余的到期时间,最后释放 leader. DelayQueue 使用排序和超时机制即实现了延迟队列.充分利用已有的 PriorityQueue 排序功能,超时阻塞又恰当好处的利用了锁的等待,在已有机制的基础上进行封装.在实际开发中,可以多多实践这一思想,使代码架构具备高复用性.
——高尔基0 前言
队首是该 Delayed 元素,其延迟在过去最远过期.
如果没有延迟已经过期,就没有head, poll将返回null.
当元素的getDelay(TimeUnit.NANOSECONDS)方法返回的值小于或等于零时,就会发生过期.
即使未到期的元素无法使用take或poll删除,它们也被视为普通的元素。 例如,size方法返回过期和未过期元素的计数.
此队列不允许空元素.
该类及其迭代器实现集合和迭代器接口的所有可选方法。方法Iterator()中提供的迭代器不能保证以任何特定的顺序遍历DelayQueue中的元素.1 继承体系
混合式的接口,用于标记在给定延迟后应作用的对象。此接口的实现还必须定义一个compareTo方法,该方法提供与其getDelay方法一致的顺序.2 属性
3 构造方法
3.1 无参
3.2 有参
4 新增数据
put
可以看到 put 调用的是 offerDelayQueue#offer
执行流程
2.元素添加到优先级队列中
3.检验元素是否为队首,是则设置 leader 为null, 并唤醒一个消费线程
4.解锁PriorityQueue#offer
public boolean offer(E e) { // 若元素为 null,抛NPE if (e == null) throw new NullPointerException(); // 修改计数器加一 modCount++; int i = size; // 如果队列大小 > 容量 if (i >= queue.length) // => 扩容 grow(i + 1); size = i + 1; // 若队列空,则当前元素正好处于队首 if (i == 0) queue[0] = e; else // 若队列非空,根据优先级排序 siftUp(i, e); return true; } 执行流程
5 取数据
take
public E take() throws InterruptedException { final ReentrantLock lock = this.lock; // 获取可中断锁 lock.lockInterruptibly(); try { for (;;) { // 从优先级队列中获取队首 E first = q.peek(); if (first == null) // 队首为 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 { // 若leader == null且还存在元素,则唤醒一个消费线程 if (leader == null && q.peek() != null) available.signal(); // 解锁 lock.unlock(); } } 执行流程
如果不想无限阻塞,可以尝试 poll 方法,设置超时时间,在超时时间内,队头元素还没有过期的> 话,就会返回 null.6 解密 leader 元素
这里假设有多个消费者线程执行 take 取数据,若没有leader != null 判断,这些线程都会无限循环,直到返回第一个元素,这显然很浪费系统资源. 所以 leader 在这里相当于一个线程标识,避免消费者线程的无脑竞争.
7 总结
本网页所有视频内容由 imoviebox边看边下-网页视频下载, iurlBox网页地址收藏管理器 下载并得到。
ImovieBox网页视频下载器 下载地址: ImovieBox网页视频下载器-最新版本下载
本文章由: imapbox邮箱云存储,邮箱网盘,ImageBox 图片批量下载器,网页图片批量下载专家,网页图片批量下载器,获取到文章图片,imoviebox网页视频批量下载器,下载视频内容,为您提供.
阅读和此文章类似的: 全球云计算
官方软件产品操作指南 (170)