一个基本得延迟订单功能做好了,在Test.java里面有测试用例,可以自己扩展更为高效得延迟订单,比如说加入消息队列什么的。下面是链接:
https://pan.baidu.com/s/1HLMeW-EIEqlKA9SDn9ffDw 密码:6t84
下面我们看好着DelayQueue大概是怎样得
put订单得时候,我们会调用offer()方法,offer()方法如下:
public boolean offer(E e) { final ReentrantLock lock = this.lock; lock.lock(); try { //q PriorityQueue优先级队列,实际上是一个堆(不指定Comparator时默认为最小堆)TOP K问题就可以使用它 q.offer(e); //入队 if (q.peek() == e) { leader = null; //q.peek() == e 时将leader线程置为空 //调用Condition的signal()方法将会唤醒再等待队列中的首节点,该节点也是到目前为止等待时间最长的节点 available.signal(); } return true; } finally { lock.unlock(); } }
取订单时,使用take(),并且得开线程执行,take方法如下:
public E take() throws InterruptedException { //lock锁 final ReentrantLock lock = this.lock; //这个会先判断当前线程是否被中断,然后抛出异常。而使用lock.lock()时,调用interrupt(),也不会抛出异常,一直去获取锁cas 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; // don't retain ref while waiting if (leader != null) //等待队列中还剩余未过期订单, available.await(); else { //take 的线程 这个因为我们take的时候,是在一个线程里while(true){take()} //因为是只开了一个线程来无限take(),如果存在多个线程一起来take()的时候,leader就有可能失去领导地位 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(); } }
到此结束吧,有兴趣的伙伴,可以想哈为什么使用leader???有什么作用???