ScheduledThreadPoolExecutor
ScheduledThreadPoolExecutor
ScheduledThreadPoolExecutor 继承自 ThreadPoolExecutor。它主要用来在给定的延迟之后运行任务,或者定期执行任务。
DelayQueue 是一个无界队列,所以 ThreadPoolExecutor 的 maximumPoolSize 在 ScheduledThreadPoolExecutor 中没有什么意义
ScheduledThreadPoolExecutor 的执行主要分为两大部分。1)当调用 ScheduledThreadPoolExecutor 的 scheduleAtFixedRate()方法或者 scheduleWithFixedDelay()方法时,会向 ScheduledThreadPoolExecutor 的 DelayQueue 添加一个实现了 RunnableScheduledFutur 接口的 ScheduledFutureTask。2)线程池中的线程从 DelayQueue 中获取 ScheduledFutureTask,然后执行任务。
ScheduledThreadPoolExecutor 为了实现周期性的执行任务,对 ThreadPoolExecutor 做了如下的修改。·使用 DelayQueue 作为任务队列。·获取任务的方式不同。·执行周期任务后,增加了额外的处理。
ScheduledThreadPoolExecutor 会把待调度的任务(ScheduledFutureTask)放到一个 DelayQueue 中。
ScheduledFutureTask 主要包含 3 个成员变量,如下。
long 型成员变量 time,表示这个任务将要被执行的具体时间。
long 型成员变量 sequenceNumber,表示这个任务被添加到 ScheduledThreadPoolExecutor 中的序号。
long 型成员变量 period,表示任务执行的间隔周期。
DelayQueue 封装了一个 PriorityQueue,这个 PriorityQueue 会对队列中的 ScheduledFutureTask 进行排序。排序时,time 小的排在前面(时间早的任务将被先执行)。如果两个 ScheduledFutureTask 的 time 相同,就比较 sequenceNumber,sequenceNumber 小的排在前面(也就是说,如果两个任务的执行时间相同,那么先提交的任务将被先执行)。
1)线程 1 从 DelayQueue 中获取已到期的 ScheduledFutureTask(DelayQueue.take())。到期任务是指 ScheduledFutureTask 的 time 大于等于当前时间。
2)线程 1 执行这个 ScheduledFutureTask。
3)线程 1 修改 ScheduledFutureTask 的 time 变量为下次将要被执行的时间。
4)线程 1 把这个修改 time 之后的 ScheduledFutureTask 放回 DelayQueue 中(DelayQueue.add())。
1)获取 Lock。2)获取周期任务。·如果 PriorityQueue 为空,当前线程到 Condition 中等待;否则执行下面的 2.2。·如果 PriorityQueue 的头元素的 time 时间比当前时间大,到 Condition 中等待到 time 时间;否则执行下面的 2.3。·获取 PriorityQueue 的头元素(2.3.1);如果 PriorityQueue 不为空,则唤醒在 Condition 中等待的所有线程(2.3.2)。3)释放 Lock。
1)获取 Lock。2)添加任务。·向 PriorityQueue 添加任务。·如果在上面 2.1 中添加的任务是 PriorityQueue 的头元素,唤醒在 Condition 中等待的所有线程。3)释放 Lock。
版权声明: 本文为 InfoQ 作者【周杰伦本人】的原创文章。
原文链接:【http://xie.infoq.cn/article/9d84c86e8ee7eb771e7e669d0】。文章转载请联系作者。
评论