ScheduledThreadPoolExecutor线程池介绍:
ScheduledThreadPoolExecutor是java提供的定时任务线程池。对应的包路径为:java.util.concurrent.ScheduledThreadPoolExecutor类结构图如下:
ScheduledThreadPoolExecutor线程池使用
// 线程池常用方法
java.util.concurrent.ScheduledThreadPoolExecutor#schedule() 定时任务
java.util.concurrent.ScheduledThreadPoolExecutor#scheduleAtFixedRate() 固定速率连续执行
java.util.concurrent.ScheduledThreadPoolExecutor#scheduleWithFixedDelay()非固定速率连续执行
java.util.concurrent.ScheduledThreadPoolExecutor.DelayedWorkQueue延迟队列
ScheduledThreadPoolExecutor线程池运行原理
ScheduledThreadPoolExecutor线程池采用DelayQueue无界队列进行定时任务提交 。
DelayQueue是一个无界队列,所以ThreadPoolExecutor的maximumPoolSize在Scheduled- ThreadPoolExecutor中没有什么意义(设置maximumPoolSize的大小没有什么效果)。
ScheduledThreadPoolExecutor的执行主要分为两大部分。
1)当调用ScheduledThreadPoolExecutor的scheduleAtFixedRate()方法或者scheduleWith- FixedDelay()方法时,会向ScheduledThreadPoolExecutor的DelayQueue添加一个实现了 RunnableScheduledFutur接口的ScheduledFutureTask。
2)线程池中的线程从DelayQueue中获取ScheduledFutureTask,然后执行任务。
ScheduledThreadPoolExecutor的实现
ScheduledThreadPoolExecutor会把待调度的任务(ScheduledFutureTask) 放到一个DelayQueue中。 ScheduledFutureTask主要包含3个成员变量,如下。
- long型成员变量time,表示这个任务将要被执行的具体时间。
- long型成员变量sequenceNumber,表示这个任务被添加到ScheduledThreadPoolExecutor中 的序号。
- ·long型成员变量period,表示任务执行的间隔周期
DelayQueue封装了一个PriorityQueue,这个PriorityQueue会对队列中的Scheduled- FutureTask进行排序。排序时,time小的排在前面(时间早的任务将被先执行)。如果两个 ScheduledFutureTask的time相同,就比较sequenceNumber,sequenceNumber小的排在前面(也就 是说,如果两个任务的执行时间相同,那么先提交的任务将被先执行)。
首先,让我们看看ScheduledThreadPoolExecutor中的线程执行周期任务的过程。
ScheduledThreadPoolExecutor运行过程
下图是 ScheduledThreadPoolExecutor中的线程1执行某个周期任务的4个步骤
1)线程1从DelayQueue中获取已到期的ScheduledFutureTask(DelayQueue.take())。到期任务 是指ScheduledFutureTask的time大于等于当前时间。
2)线程1执行这个ScheduledFutureTask。
3)线程1修改ScheduledFutureTask的time变量为下次将要被执行的时间。
4)线程1把这个修改time之后的ScheduledFutureTask放回DelayQueue中(DelayQueue.add())。