也是看了 渴死的火烈鸟 的博客才意识到的。原文http://standalone.iteye.com/blog/1876771
import java.util.concurrent.DelayQueue; public class DelayQueueExample { /** * @param args */ public static void main(String[] args) { // TODO Auto-generated method stub DelayQueue<DelayedElement> dq=new DelayQueue<DelayedElement>(); long now = System.currentTimeMillis(); System.out.println("current time in ms: " + now); DelayedElement ob1=new DelayedElement("e1", now + 1000); DelayedElement ob2=new DelayedElement("e2", now + 3000); DelayedElement ob3=new DelayedElement("e3", now + 1500); dq.add(ob1); dq.add(ob2); dq.add(ob3); try { Thread.sleep(1); } catch (InterruptedException e) { throw new RuntimeException( e ); } while(dq.size() > 0){ try { DelayedElement e = dq.take(); System.out.println("current time in ms: " + System.currentTimeMillis() + ", element:" + e.name); } catch (InterruptedException e) { throw new RuntimeException( e ); } } } }
DelayQueue源码
public class DelayQueue<E extends Delayed> extends AbstractQueue<E> implements BlockingQueue<E>
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(TimeUnit.NANOSECONDS); if (delay > 0) { long tl = available.awaitNanos(delay); } else { E x = q.poll(); assert x != null; if (q.size() != 0) available.signalAll(); // wake up other takers return x; } } } } finally { lock.unlock(); } }
DelayedElement必须继承Delayed抽象类,并且重写getDelay方法
1 package com.xqy; 2 3 import java.util.concurrent.Delayed; 4 import java.util.concurrent.TimeUnit; 5 6 public class DelayedElement implements Delayed { 7 8 public long time; 9 public String name; 10 public DelayedElement(String name, long time){ 11 this.name = name; 12 this.time = time; 13 } 14 @Override 15 public int compareTo(Delayed o) { 16 // TODO Auto-generated method stub 17 if(this.time < ((DelayedElement)o).time) return -1; 18 else if(this.time > ((DelayedElement)o).time)return 1; 19 else return 0; 20 } 21 22 @Override 23 public long getDelay(TimeUnit unit) { 24 // TODO Auto-generated method stub 25 long r = unit.convert(time - System.currentTimeMillis(), TimeUnit.MILLISECONDS); 26 System.out.println("delay:" + r); 27 return r; 28 } 29 30 }
注意上面第25行的方法
unit.convert(time - System.currentTimeMillis(), TimeUnit.MILLISECONDS)
第一个参数为数字,第二个参数为数字代表的时间单位,这里作为毫秒
执行convert后,返回unit当前的时间单位,此处是纳秒
如果第二个参数写成纳秒,
TimeUnit.NANOSECONDS,则这个转换函数转换前后数值相等,但是DelayQueue的take方法中
if (delay > 0) { long tl = available.awaitNanos(delay); }
等待的时间将缩短,上面的for循环重复执行将近原来的1000倍。这样会造成CPU空转,是load升高。