定时任务 & 定时线程池

定时线程池

使用场景:

1. 分布式锁 - redis

2. springCloud - 服务注册与发现中心

ScheduledThreadPoolExecutor

它用来处理延时任务或定时任务。

 

 

 

它接收SchduledFutureTask类型的任务,是线程池调度任务的最小单位,有三种提交任务的方式:

  1. schedule
  2. scheduledAtFixedRate
  3. scheduledWithFixedDelay

它采用DelayQueue存储等待的任务

  1. DelayQueue内部封装了一个PriorityQueue,它会根据time的先后时间排序,若time相同则根据sequenceNumber排序;
  2. DelayQueue也是一个无界队列;

任务提交上来后,会将任务封装为一个ScheduledFutureTask

SchduledFutureTask接收的参数(成员变量):
  1. private long time:任务开始的时间
  2. private final long sequenceNumber;:任务的序号
  3. private final long period:任务执行的时间间隔 
工作线程的执行过程:
  工作线程会从DelayQueue取已经到期的任务去执行; 执行结束后重新设置任务的到期时间,再次放回DelayQueue。
ScheduledThreadPoolExecutor会把待执行的任务放到工作队列DelayQueue中, DelayQueue封装了一个PriorityQueue,PriorityQueue会对队列中的ScheduledFutureTask进行排序,具体的排序算法实现如下: 
1. 首先按照time排序,time小的排在前面,time大的排在后面;
2. 如果time相同,按照sequenceNumber排序,sequenceNumber小的排在前面,sequenceNumber大的排在后面,换句话说,如果两个task的执行时间相同, 优先执行先提交的task。 
 
SchduledFutureTask之run方法实现 run方法是调度task的核心,task的执行实际上是run方法的执行:
1 public void run() {

2  boolean periodic = isPeriodic();

3 //如果当前线程池已经不支持执行任务,则取消

4  if (!canRunInCurrentRunState(periodic))

5  cancel(false);

6 //如果不需要周期性执行,则直接执行run方法然后结束

7  else if (!periodic)

8  ScheduledFutureTask.super.run();

9 //如果需要周期执行,则在执行完任务以后,设置下一次执行时间

10  else if (ScheduledFutureTask.super.runAndReset()) {

11  // 计算下次执行该任务的时间

12  setNextRunTime();

13  //重复执行任务

14  reExecutePeriodic(outerTask);

15  }

16 }

1. 如果当前线程池运行状态不可以执行任务,取消该任务,然后直接返回,否则执行 步骤2;

2. 如果不是周期性任务,调用FutureTask中的run方法执行,会设置执行结果,然后 直接返回,否则执行步骤3;

3. 如果是周期性任务,调用FutureTask中的runAndReset方法执行,不会设置执行 结果,然后直接返回,否则执行步骤4和步骤5;

4. 计算下次执行该任务的具体时间;

5. 重复执行任务。 

DelayedWorkQueue 

ScheduledThreadPoolExecutor之所以要自己实现阻塞的工作队列,是因为 ScheduledThreadPoolExecutor要求的工作队列有些特殊。

ScheduledThreadPoolExecutor之所以要自己实现阻塞的工作队列,是因为 ScheduledThreadPoolExecutor要求的工作队列有些特殊。 DelayedWorkQueue是一个基于堆的数据结构,类似于DelayQueue和 PriorityQueue。在执行定时任务的时候,每个任务的执行时间都不同,所以 DelayedWorkQueue的工作就是按照执行时间的升序来排列,执行时间距离当前时间越近 的任务在队列的前面(注意:这里的顺序并不是绝对的,堆中的排序只保证了子节点的下次 执行时间要比父节点的下次执行时间要大,而叶子节点之间并不一定是顺序的)。

heap -》堆结构

  1. 最小根堆

  2. 最大根堆

 存储数据结构是一个数组。

End!

posted @ 2022-11-12 05:11  君莫笑我十年游  阅读(161)  评论(0编辑  收藏  举报