DelayQueue 队列

 DelayQueue----一种有序队列,特点就是只有在队列中的元素到期后才能取出。

              1.内存中哪些对象到了超时时间,需要从内存中清除出去。

              2.服务器连接中有哪些连接很长时间未操作,需要关闭这些连接

              3.任务中有哪些到了执行时间,该进行调度了。

简单的方法就是写一个线程不断去检查每一项是否到了时间,但这种方法在队列中的元素非常多的情况下会不准确或太耗费性能,用DelayQueue可完美地解决这个问题。


假设镇上开了一家无限大的网吧,每人交一块钱可以上一分钟网(过年时的网吧坑爹程度差不多就这样);

             网吧比较老式没有先进的管理系统,为了知道哪个家伙时间到该下机了,老板得一台一台地去看,上网的人一多等老板把整个网吧转一遍有些家伙早超时了,而且老板要一遍一遍地检查也累个半死;

             有一天某个人给老板开发了个简单的程序,这个程序可以自动将上机的人排序,并在恰当的时间告诉老板哪个家伙时间到了。这个程序大概会是这样:

[java]  view plain  copy
  1. public class Wangming implements Delayed {  
  2.   
  3.     private String name;  
  4.     //身份证  
  5.     private String id;  
  6.     //截止时间  
  7.     private long endTime;  
  8.       
  9.     public Wangming(String name,String id,long endTime){  
  10.         this.name=name;  
  11.         this.id=id;  
  12.         this.endTime=endTime;  
  13.     }  
  14.       
  15.     public String getName(){  
  16.         return this.name;  
  17.     }  
  18.       
  19.     public String getId(){  
  20.         return this.id;  
  21.     }  
  22.       
  23.     /** 
  24.      * 用来判断是否到了截止时间 ,
    *
    getDelay(TimeUnit unit)方法应该返回以纳秒为单位的时间差,而不是如博主所写的毫秒为单位的时间差
  25.      */  
  26.     @Override  
  27.     public long getDelay(TimeUnit unit) {  
  28.         // TODO Auto-generated method stub  
  29.         return endTime-System.currentTimeMillis();  
  30.     }  
  31.   
  32.     /** 
  33.      * 相互批较排序用 
  34.      */  
  35.     @Override  
  36.     public int compareTo(Delayed o) {  
  37.         // TODO Auto-generated method stub  
  38.         Wangming jia = (Wangming)o;  
  39.         return endTime-jia.endTime>0?1:0;  
  40.     }  
  41.   
  42. }  

[java]  view plain  copy
  1. public class WangBa implements Runnable {  
  2.   
  3.     private DelayQueue<Wangming> queue = new DelayQueue<Wangming>();  
  4.     public boolean yinye =true;  
  5.       
  6.     public void shangji(String name,String id,int money){  
  7.         Wangming man = new Wangming(name,id,1000*60*money+System.currentTimeMillis());        
  8.         System.out.println("网名"+man.getName()+" 身份证"+man.getId()+"交钱"+money+"块,开始上机...");  
  9.         this.queue.add(man);  
  10.     }  
  11.       
  12.     public void xiaji(Wangming man){  
  13.         System.out.println("网名"+man.getName()+" 身份证"+man.getId()+"时间到下机...");  
  14.     }  
  15.   
  16.     @Override  
  17.     public void run() {  
  18.         // TODO Auto-generated method stub  
  19.         while(yinye){  
  20.             try {  
  21.                 System.out.println("检查ing");  
  22.                 Wangming man = queue.take();  
  23.                 xiaji(man);  
  24.             } catch (InterruptedException e) {  
  25.                 // TODO Auto-generated catch block  
  26.                 e.printStackTrace();  
  27.             }  
  28.         }  
  29.     }  
  30.       
  31.     public static void main(String args[]){  
  32.         try{  
  33.             System.out.println("网吧开始营业");  
  34.             WangBa siyu = new WangBa();  
  35.             Thread shangwang = new Thread(siyu);  
  36.             shangwang.start();  
  37.               
  38.             siyu.shangji("路人甲""123"1);  
  39.             siyu.shangji("路人乙""234"2);  
  40.             siyu.shangji("路人丙""345"1);  
  41.         }  
  42.         catch(Exception ex){  
  43.               
  44.         }  
  45.   
  46.     }  
  47. }  

运行结果:

[html]  view plain  copy
  1. 网吧开始营业  
  2. 检查ing  
  3. 网名路人甲 身份证123交钱1块,开始上机...  
  4. 网名路人乙 身份证234交钱2块,开始上机...  
  5. 网名路人丙 身份证345交钱1块,开始上机...  
  6. 网名路人甲 身份证123时间到下机...  
  7. 检查ing  
  8. 网名路人丙 身份证345时间到下机...  
  9. 检查ing  
  10. 网名路人乙 身份证234时间到下机...  
  11. 检查ing  

从上面的运行结果可以看出,程序并没有一遍一遍地扫描队列中的对象,而是在队列中没有对象符合条件时阻塞。

有了这个程序老板邪恶地笑了,他这下子可以舒舒服服地坑爹了。


至于这个好不好用呢,用过才知道,尤其是在并发量比较大的情况下。

DelayQueue 的内部是一个优先队列,从数据结构上看是一个类有序二叉树:

offer、poll、remove() 和 add------ O(log(n)) 时间;
remove(Object) 和 contains(Object) ------线性时间;
peek、element 和 size-------固定时间


Java中的DelayQueue是一个特殊的队列,它只允许在指定的延迟时间之后才能从队列中取出元素。可以使用DelayQueue来实现一些延迟任务的功能,例如任务调度、缓存过期等。 DelayQueue基于PriorityQueue实现,但是它的元素必须实现Delayed接口,Delayed接口中定义了一个getDelay()方法,返回元素的延迟时间。 当从DelayQueue中取出元素时,如果该元素的延迟时间还没有到达,则该元素会被重新加入队列中,直到延迟时间到达。 以下是一个简单的使用DelayQueue的例子: ```java import java.util.concurrent.DelayQueue; import java.util.concurrent.Delayed; import java.util.concurrent.TimeUnit; public class DelayQueueExample { public static void main(String[] args) throws InterruptedException { DelayQueue<DelayedElement> delayQueue = new DelayQueue<DelayedElement>(); delayQueue.add(new DelayedElement("element1", 2000)); delayQueue.add(new DelayedElement("element2", 5000)); delayQueue.add(new DelayedElement("element3", 1000)); while (!delayQueue.isEmpty()) { DelayedElement element = delayQueue.take(); System.out.println("Taking element: " + element); } } static class DelayedElement implements Delayed { private String name; private long delayTime; public DelayedElement(String name, long delayTime) { this.name = name; this.delayTime = System.currentTimeMillis() + delayTime; } @Override public long getDelay(TimeUnit unit) { long diff = delayTime - System.currentTimeMillis(); return unit.convert(diff, TimeUnit.MILLISECONDS); } @Override public int compareTo(Delayed o) { if (this.delayTime < ((DelayedElement) o).delayTime) { return -1; } if (this.delayTime > ((DelayedElement) o).delayTime) { return 1; } return 0; } @Override public String toString() { return "DelayedElement{" + "name='" + name + '\'' + ", delayTime=" + delayTime + '}'; } } } ``` 在上面的例子中,我们创建了一个DelayQueue,并向其中添加了三个DelayedElement元素。每个元素都有一个延迟时间,分别为2秒、5秒和1秒。 在主线程中,我们不断地从DelayQueue中取出元素,直到队列为空。当元素的延迟时间还没有到达时,它会被重新加入队列中,直到延迟时间到达。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值