scheduledThreadPoolExecutor 原理 delayedQueue

背景

这种定时器也常用,不好奇怎么实现的吗?!

参考

https://juejin.im/post/5d63ce9b6fb9a06b28635ecf

demo

先看个demo吧
在这里插入图片描述

package com.vava.ecommerse.scheduler;

import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

/**
 * @author Steve
 * Created on 2020-06
 */
@Component
public class SchedulerDemo {

    @Scheduled(cron = "1 * * * * ?")
    public void task1(){
        System.out.println("test when sec=1");
        Thread thread =  Thread.currentThread();
        System.out.println("ThreadName:" + thread.getName() + ",id:" + thread.getId() + ",group:" + thread.getThreadGroup());

    }

    @Scheduled(fixedDelay = 5000)
    public void task2(){
        System.out.println("test fixed delay = 5000");
        Thread thread =  Thread.currentThread();
        System.out.println("ThreadName:" + thread.getName() + ",id:" + thread.getId() + ",group:" + thread.getThreadGroup());

    }

}

过程

总体的思路是这样的:
1、在beanpostprocessor中处理注解相关逻辑,将任务注册。
2、applicationListener中触发schedule
3、每个schedule会计算下一次触发的时间,然后扔进去executor中延时执行
在这里插入图片描述
4、executor到时间就会执行相应的run方法
在这里插入图片描述
执行完指定的任务之后,就会再调用schedule(),回到第3步,再计算下一次的执行时间,然后扔进executor等待执行。

如何实现delay一段时间然后执行呢?

上面我们看到调用this.executor.schedule(this, initialDelay, TimeUnit.MILLISECONDS);
就可以delay一段时间然后执行相应的代码。具体是怎么实现的呢?

这里我们的executor是scheduledThreadPoolExecutor,可以step into看一下

在这里插入图片描述

包装了一下成为RunnableScheduledFuture,然后delayedExecute(t),再step into
在这里插入图片描述

把任务加到队列中。。

然后就会有地方消费这个队列里的任务才是。。?
参考:https://tech.meituan.com/2020/04/02/java-pooling-pratice-in-meituan.html
也就是这个:
在这里插入图片描述

ScheduledThreadPoolExecutor内部使用一个DelayedWorkQueue
在这里插入图片描述
这理论上是一个延时队列,本质上是个优先级队列,按照剩余时间的多少排序的队列。

在这里插入图片描述

优先级队列其实是一个堆。
在这里插入图片描述
按照堆的算法向上向下挪

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章