通过扩展 PriorityBlockingQueue 的 take() 实现任务定时触发

来源:互联网 发布:韩庚偷电脑知乎 编辑:程序博客网 时间:2024/05/17 01:37

        考虑这样一种情况:在一个系统中,前台可以发送一系列任务给后台执行,且任务具有定时的特性,对定时的处理,要求在后台处理,也就是说,前台不关心任务的开始i时间,只负责发送任务,后台在接收到任务之后,要判断任务的开始时间,如果开始时间没有到,需要将任务放入一个队列中,然后等待任务开始时间到了再将其取出执行。

        对于这样的问题,可以采用定时器来处理:对于每一个开始时间没有到的任务,为其启动一个定时器,定时触发任务执行。但这种处理方式有两个问题:1.任务如果很多,为每个任务开启专用的定时器,必然会增加程序的复杂性和系统的负载。2.每个定时器对应一个线程,而在上面的情况下,显然最好是不要用多线程去处理的,考虑下在什么情况下适合用多线程,就会明白为什么了。

         其实,对于上面的问题,可以通过扩展 PriorityBlockingQueue 的 take() 方法来完成功功能。

         在 PriorityBlockingQueue 队列中没有元素的情况下,调用其 take() 方法,会阻塞,直到有元素可被取出,或者被中断。我们可以将上面提到的具有定时特殊性的任务,按照开始时间的顺序:开始时间早的,存放在 PriorityBlockingQueue  队列中的前面,开始时间迟的,存放在后面,然后重写 take()方法,重写之后,当 take()方法被调用时,即使队列中有元素,也不会立刻将其返回,而是阻塞等待队列中最前面(最前面的一定是开始时间最早的任务)的任务开始时间到,才会将其返回。

为达到上面的目的,必须解决以下几个问题:

        <1>. 如何实现将开始时间早的任务放在队列的前面,开始时间晚的任务,放在队列的后面?

        <2>. take()方法内部,如何实现上面期望的功能(任务开始时间到才被返回)?

       第一个问题比较容易解决:PriorityBlockingQueue 本身就是一个优先级队列,可以根据开始时间自定义任务的优先级,为此需让任务继承 Comparable 接口,然后重写其compareTo()方法即可。

        第二个问题,可以在 take() 方法内部启一个监控线程,监视开始时间最早的任务,待其开始时间到了,再将其返回。这里存在一个问题:在监视开始时间最早任务的过程中,如果有开始时间更早的任务到来,该如何处理?显然,此时需要将监控线程打断,让它去监控这个更早的任务,显然 offer() 方法也需要被重写。

        具体的代码实现就不贴了。




原创粉丝点击