一文带你搞懂 ScheduledExecutorService 定时任务类(一)

497 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第11天,点击查看活动详情

前言

在之前学习 RocketMQ 源码的过程中,生产者 DefaultMQProducer 启动时,会初始化一个定时任务类 ScheduledExecutorService:

image.png

它的作用对于 DefaultMQProducer 而言,是定时执行以下任务的:

  • 如果 NameServer 的地址是空的,定时查询并更新本地缓存的 NameServer 地址
  • 定时查询并更新本地缓存的 Topic 路由信息
  • 定时从本地缓存中移除已经下线的 Broker 信息以及定时发送心跳包给所以的 NameServer
  • 定时持久化 Consumer 的 offset
  • 定时调整线程池
  • ......

应用Demo

ScheduledExecutorService 主要有以下四个方法,我们比较常用的有两个

image.png

  • scheduleAtFixedRate 方法:执行任务的线程;任务启动的延迟时间;一次任务执行后下一次任务开始的时间间隔。
  • scheduleWithFixedDelay 方法:执行任务的线程,任务启动的延迟时间,一次任务执行启动,下一次任务开始的时间间隔。

它们的区别,简而言之就是

  • scheduleAtFixedRate 的执行周期是:需要等前一个任务执行完毕后,才能开启下一个任务;否则将一直等待
  • scheduleWithFixedDelay 的执行周期是:一个任务开始执行了,到达时间间隔后,下一个任务就开始了,不会等待

可以看看我这个 Demo 的输出结果

  • scheduleAtFixedRate 测试代码: image.png

  • 结果分析:第一次任务执行的时间为:22:30:14,本来根据定义,第二次任务的执行时间应该是 22:30:16,但由于任务卡了5秒,所以第二次任务执行需要等到第一次任务执行完成,所以第二次任务的执行时间变成了22:30:19;第三次任务同理,以此类推 image.png

  • scheduleWithFixedDelay 测试代码:

    image.png

  • 结果分析:第一次任务执行的时间为:22:38:14,本来根据定义,第二次任务的执行时间应该是 22:30:16,但为啥这里还是过了5秒后才执行第二次任务呢?这是因为啊,ScheduledExecutorService 线程池里只初始化了一个线程,所以只能够等其中一个线程释放了,放回线程池后,再从线程池中把这个线程取出来执行任务~

    image.png

小结

今天简单了解了 ScheduledExecutorService 定时任务类线程池的用法,了解了 scheduleAtFixedRate 和 scheduleWithFixedDelay 方法的区别,明天,我们一起来看看多个线程下 scheduleAtFixedRate 和 scheduleWithFixedDelay 执行的逻辑又是如何的?也一起来看看 ScheduledExecutorService 的实现原理。大家多多关注哦~