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
在這裏插入圖片描述
這理論上是一個延時隊列,本質上是個優先級隊列,按照剩餘時間的多少排序的隊列。

在這裏插入圖片描述

優先級隊列其實是一個堆。
在這裏插入圖片描述
按照堆的算法向上向下挪

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