Jdk1.6 JUC源码解析(18)-DelayQueue
作者:大飞
功能简介:
- DelayQueue是一种无界的阻塞队列,队列里只允许放入可以"延期"的元素,队列中列头的元素是最先"到期"的元素。如果队列中没有任何元素"到期",尽管队列中有元素,也不能从队列头获取到任何元素。
源码分析:
- 首先还是看一下内部数据结构:
public class DelayQueue<E extends Delayed> extends AbstractQueue<E> implements BlockingQueue<E> { private transient final ReentrantLock lock = new ReentrantLock(); private transient final Condition available = lock.newCondition(); private final PriorityQueue<E> q = new PriorityQueue<E>();
内部结构非常简单,一把锁,一个条件,一个优先队列。
DelayQueue要求放入其中的元素必须实现Delayed接口,看下这个接口:
/** * A mix-in style interface for marking objects that should be * acted upon after a given delay. * * <p>An implementation of this interface must define a * <tt>compareTo</tt> method that provides an ordering consistent with * its <tt>getDelay</tt> method. * * @since 1.5 * @author Doug Lea */ public interface Delayed extends Comparable<Delayed> { /** * Returns the remaining delay associated with this object, in the * given time unit. * * @param unit the time unit * @return the remaining delay; zero or negative values indicate * that the delay has already elapsed */ long getDelay(TimeUnit unit); }
这个接口定义了一个返回延时值的方法,而且扩展了Comparable接口,具体实现的排序方式会和延时值有关,延时值最小的会排在前面。再结合上面DelayQueue的内部数据结构,我们就可以大概脑补这个过程了。
- 既然是阻塞队列,还是从put和take方法开始入手,先看下put方法:
public boolean offer(E e) { final ReentrantLock lock = this.lock; lock.lock(); try { //获取队头元素。 E first = q.peek(); //将元素放入内部队列。 q.offer(e); if (first == null || e.compareTo(first) < 0) available.signalAll(); //如果队头没有元素 或者 当前元素比队头元素的延时值小,那么唤醒available条件上的线程。 return true; } finally { lock.unlock(); } } /** * 插入一个元素到延迟队列,由于队列是无界的,所以这个方法永远不会阻塞。 * * @param e the element to add * @throws NullPointerException {@inheritDoc} */ public void put(E e) { offer(e); }
再看下take方法:
public E take() throws InterruptedException { final ReentrantLock lock = this.lock; lock.lockInterruptibly(); try { for (;;) { //获取队头元素。 E first = q.peek(); if (first == null) { available.await();//如果队头没有元素,那么当前线程在available条件上等待。 } else { //如果队头有元素,获取元素的延时值。 long delay = first.getDelay(TimeUnit.NANOSECONDS); if (delay > 0) { //如果延时值大于0,那么等待一下。 long tl = available.awaitNanos(delay); } else { //否则获取并移除队列列头元素。 E x = q.poll(); assert x != null; if (q.size() != 0) available.signalAll(); // 如果内部队列中还有元素,那么唤醒其他在available条件上等待着的take线程。 return x; } } } } finally { lock.unlock(); } }
- 其他方法代码也很简单,这里不做分析了。最后注意下本类的迭代器是弱一致的,并且不保证元素的特定顺序。
DelayQueue的代码解析完毕!
相关推荐
JDK 1.6 64位(jdk-6u45-windows-x64(1.6 64))
aspose-words-15.8.0-jdk1.6aspose-words-15.8.0-jdk1.6aspose-words-15.8.0-jdk1.6aspose-words-15.8.0-jdk1.6aspose-words-15.8.0-jdk1.6aspose-words-15.8.0-jdk1.6aspose-words-15.8.0-jdk1.6aspose-words-...
2部分: jdk-1.6-windows-64-01 jdk-1.6-windows-64-02
三部分: jdk-1.6-linux-64-1 jdk-1.6-linux-64-2 jdk-1.6-linux-64-3
1.okhttp3.8源码使用jdk1.6重新编译,已集成了okio,在javaweb项目中使用,未在安卓项目中使用 2.okhttp3.8源码使用jdk1.6重新编译_okhttp3.8.0-jdk1.6.jar
三部分: jdk-1.6-linux-64-1 jdk-1.6-linux-64-2 jdk-1.6-linux-64-3
jdk-jdk1.6.0.24-windows-i586.exe
三部分: jdk-1.6-linux-64-1 jdk-1.6-linux-64-2 jdk-1.6-linux-64-3
logback-cfca-jdk1.6-3.1.0.0.jar
文档介绍了JDK1.6安装及与JDK-1.5版本共存,已经在我的机子上通过了测试,按照文档操作即可。
jdk-1.6-linux-32-1 jdk-1.6-linux-32-2 jdk-1.6-linux-32-3
JDK-1.6-Windows-32位 纯官方安装版 JDK-1.6-Windows-32位 纯官方安装版
jdk-1.6-linux-32-1 jdk-1.6-linux-32-2 jdk-1.6-linux-32-3
jdk-1.6-windows-32-1 jdk-1.6-windows-32-2 jdk-1.6-windows-32-3
三部分: jdk-1.6-windows-32-1 jdk-1.6-windows-32-2 jdk-1.6-windows-32-3
三部分: jdk-1.6-windows-32-1 jdk-1.6-windows-32-2 jdk-1.6-windows-32-3
Java编程开发工具包,最新版本,很好用,经典
1、okhttp3.8源码使用jdk1.6重新编译,已集成了okio,仅在javaweb项目中使用。 2、另附json-20160810.jar
jdk1.6-jdk-6u43-windows32-i586
java环境搭建 jdk6(包含jre)64位 jdk-6u45-windows-x64