美文网首页工作生活
10 一张图就搞懂spring定时任务

10 一张图就搞懂spring定时任务

作者: cjxz | 来源:发表于2019-07-02 17:29 被阅读0次

直接上图

image.png

spring定时任务是通过JDK的ThreadPoolTaskScheduler实现的。

spring中处理逻辑

  • 解析task命名空间,将定时任务的数据通过IOC解析成为BeanDefinition
  • 在创建Bean对象时,处理BeanDefinition数据实例化一下对象:
    • CronTask这个对象中包含了cron任务触发器和需要执行的任务Runnable对象
    • ScheduledMethodRunnable这个对象中包含了Method和target并且实现Runnable接口这个Runnable接口最后会进入JAVA中的线程池中
    • ThreadPoolTaskScheduler在spring中创建JAVA的线程池对象,前面创建的CronTaskScheduledMethodRunnable注册到线程池中
  • 所有的任务都会创建上面的CronTaskScheduledMethodRunnable然后注册到同一个线程池中ThreadPoolTaskScheduler
  • 进入java代码逻辑

java代码逻辑

每一个任务进入ThreadPoolTaskScheduler。不知道大家有没有想过定时任务执行的方式是如何左右定时执行的?假设现在有1000个任务我怎么知道下一个即将执行的定时任务呢?

方案1(不好的实现方式)

通过一个比较小的时间单位,例如1秒钟遍历一次定时任务队列,查看里面那个任务需要执行。这种方案很容易就被否定了。因为如果数据量比较大,每次遍历队列很有可能1秒钟都无法遍历完毕,而且这种时间也不准确。

方案2(优先级队列)

如果学过堆这种数据结构的同学应该知道的最佳实践——优先级队列

堆的定义

  • 堆是一个满二叉树,满二叉树最好的存储方式就是数组因为这样查询数据的时间复杂度为O(1)可以根据下标直接访问。
  • 堆里面的任意一个父节点的所有子节点要么大于等于(小于)其父节点的数据。下面我画了个图,其中1,2是大顶堆;3是小顶堆;4不是堆

分析优先级队列在ThreadPoolTaskScheduler中的使用。在spring中已经创建的Runnable和触发器。每次向队列中添加一个task的时候需要判断滞后时间最小的数据放到堆顶,这样在从队列中获取任务的时候就可以直接拿堆顶(队首)元素判断队首元素执行时间和当前时间对比,如果滞后时间大那么需要将当前线程利用LockSupper工具将当前线程挂起n毫秒,n毫秒到了之后当前线程继续执行,然后调用Runnable接口的run方法。也就是ScheduledMethodRunnable的run方法

相关文章

网友评论

    本文标题:10 一张图就搞懂spring定时任务

    本文链接:https://www.haomeiwen.com/subject/ecdthctx.html