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

    xiaoxiao2021-04-14  79

    这篇文章我们来讲讲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; } @Override public int compareTo(Delayed arg) { DelayTask delay = (DelayTask) arg; if(this.trigger==delay.trigger){ return 0; } //必须要越晚到期的元素越排后,因为队列是先进先出的,最先弹出的元素是队头,所以队头必须是最先到期的 //当然,如果不这样做也不会有任何报错,只是,本来等待3秒某个任务必须要执行了 //但由于队头要等待10秒,在队头没有被弹出之前,该任务是无法弹出的; return this.trigger > delay.trigger?1:-1; } //返回与此对象相关的剩余延迟时间,以给定的时间单位表示。 @Override public long getDelay(TimeUnit unit) { return unit.convert(trigger-System.currentTimeMillis(), TimeUnit.MILLISECONDS); } @Override public 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() { @Override public 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毫秒内,   没错,一切都在我们的预料之中,延时时间越短的线程将先得到执行;

    转载请注明原文地址: https://ju.6miu.com/read-670491.html

    最新回复(0)