进阶篇:延时队列之DelayQueue(十四)

来源:互联网 发布:知误会前番书语 编辑:程序博客网 时间:2024/06/05 17:04

这篇文章我们来讲讲BlockingQueue阻塞队列的另一个实现DelayQueue,先前我们的文章中有介绍LinkedBlockingQueue,而DelayQueue与之不同的是,DelayQueue里面哪怕有元素也无法取出,除非元素已经到期,而LinkedBlockingQueue只要里面有元素就可以取出!


所以,你可以往DelayQueue中存放一个元素,且声明在半小时后才失效。那么往此队列中取元素的线程将会阻塞半小时,直到半小时后才能拿到元素进行下一步动作,这样的话,你就可以变相实现定时执行任务了;当然,我们是不会这样来用的,定时任务有更完美的解决方案,这个我们后面再介绍;


class DelayTask implements Delayed,Runnable{long trigger = 0;//触发时间,也就是队列中的元素失效时间int id = 0;long delayMilliSecound = 0;//等待时间public DelayTask( long delayMilliSecound,int id) {this.delayMilliSecound = delayMilliSecound;this.trigger = System.currentTimeMillis()+delayMilliSecound;this.id = id;}@Overridepublic int compareTo(Delayed arg) {DelayTask delay = (DelayTask) arg;if(this.trigger==delay.trigger){return 0;}//必须要越晚到期的元素越排后,因为队列是先进先出的,最先弹出的元素是队头,所以队头必须是最先到期的//当然,如果不这样做也不会有任何报错,只是,本来等待3秒某个任务必须要执行了//但由于队头要等待10秒,在队头没有被弹出之前,该任务是无法弹出的;return this.trigger > delay.trigger?1:-1;}//返回与此对象相关的剩余延迟时间,以给定的时间单位表示。@Overridepublic long getDelay(TimeUnit unit) {return unit.convert(trigger-System.currentTimeMillis(), TimeUnit.MILLISECONDS);}@Overridepublic void run() {System.out.println("任务"+id+"开始运行,等待时间为:"+delayMilliSecound);}}


//DelayQueue,存放Delayed元素的一个无界阻塞队列,只有在某个元素的延迟期满时才能从中提取元素,它和LinkedBlockingQueue不同的是,//DelayQueue里面哪怕有元素也无法取出,除非元素已经到期,也就是getDelay()返回值<=0;//而LinkedBlockingQueue只要里面有元素就可以取出!//DelayQueue也可以看成是一个变相的优先级队列;也就是说,越快失效的元素越能优先取出!public static void delayQueue() throws InterruptedException{final DelayQueue<DelayTask> queue = new DelayQueue<DelayTask>();Random random = new Random();for (int i = 0; i < 10; i++) {queue.put(new DelayTask(random.nextInt(5000),i+1));}//开启一个消费者线程消费队列中的任务new Thread(new Runnable() {@Overridepublic void run() {System.out.println("开始消费队列中的任务!");while( !Thread.currentThread().isInterrupted()){try {//取出队列中的元素queue.take().run();} catch (InterruptedException e) {e.printStackTrace();}}}}).start();//等任务全部消费完毕,再往队列里面塞一个ID为100,延期3秒的任务!TimeUnit.MILLISECONDS.sleep(6000);queue.put(new DelayTask(3000, 100));}


注意:DelayQueue中存放的对象必须实现Delayed接口的compareTo方法与getDelay方法!


看一下输出:************************************************************************

开始消费队列中的任务!
任务4开始运行,等待时间为:554
任务9开始运行,等待时间为:729
任务5开始运行,等待时间为:917
任务3开始运行,等待时间为:1079
任务1开始运行,等待时间为:1652
任务10开始运行,等待时间为:2969
任务2开始运行,等待时间为:3676
任务7开始运行,等待时间为:3829
任务6开始运行,等待时间为:4252
任务8开始运行,等待时间为:4294
任务100开始运行,等待时间为:3000

**************************************************************************************

我们先往queue中塞入了十个DelayTask实例,且指定延时时间为随机5000毫秒内,   没错,一切都在我们的预料之中,延时时间越短的线程将先得到执行;


0 0
原创粉丝点击