newScheduledThreadPool : scheduleAtFixedRate 与 scheduleWithFixedDelay 详解

一.引言


newScheduledThreadPool 周期性线程池提供了周期执行任务的方法 scheduleAtFixedRate 与 scheduleWithFixedDelay,两者比较容易混淆,下面结合代码捋一下逻辑,后续使用也更加方便。

二.功能介绍


1.scheduleAtFixedRate Api 
   

public ScheduledFuture<?> scheduleAtFixedRate(Runnable command,
                                                  long initialDelay,
                                                  long period,
                                                  TimeUnit unit)


官方解释 : 创建并执行一个周期性操作,该操作在给定的初始延迟之后首先启用,然后在给定的时间段内启用;也就是说,执行将在initialDelay之后开始,然后是initialDelay+period,然后是initialDelay+2*period,依此类推。

如果任务的任何执行遇到异常,则禁止后续执行。否则,只能通过取消或终止执行者来终止任务。如果此任务的任何执行时间长于其周期,则后续执行可能会延迟开始,但不会同时执行。

执行逻辑 : initiaDelay时间结束后,从上一个任务开始计时,period 时间后,检查上一个任务,如果上一个任务执行完成则立即执行新任务,如果未完成则等待上一个任务完成立即执行,循环往复

理想状态 : initiaDelay时间结束后,每 period 时间内,任务正常执行一次 

举个列子 : 60min时间里每个10min内都做一次执行时间小于等于10min的Runnable的任务

2.scheduleWithFixedDelay Api
   

public ScheduledFuture<?> scheduleWithFixedDelay(Runnable command,
                                                     long initialDelay,
                                                     long delay,
                                                     TimeUnit unit);


官方解释 : 创建并执行一个周期性操作,该操作在给定的初始延迟之后首先启用,然后在一个执行的终止和下一个执行的开始之间具有给定的延迟。如果任务的任何执行遇到异常,则禁止后续执行。否则,只能通过取消或终止执行者来终止任务。

执行逻辑 : initiaDelay时间结束后,从上一个任务结束开始计时delay 时间过后,立即执行下一个任务,注意这里不会检查上一个任务是否执行完毕

理想状态 : initiaDelay时间结束后,任务依次间隔执行,每个任务之间间隔 delay

举个列子 : 每个Runnable都正常执行,Runnable A 结束后过 delay 时间 Runnable B 执行,one by one 以此类推

3.相同与不同
相同点 :

都具有延时初始化的方式,周期/间隔性的执行任务,都只实现了Runnable方法,不像 newScheduledThreadPool 的  schedule 同时支持 Runnalbe 和 Callable,都需要做好完备的Try Catch,否则中途失败只能通过取消或终止 executor 来终止任务

不同点 :

scheduleAtFixedRate 以 period 为单位,所以是周期执行,

scheduleWithFixedDelay 以 delay 为单位,所以是按间隔执行

三.实战


下面通过两个简单例子讲解一下使用,两个例子我都会在线程池中额外加一个线程池负责计数,每1s钟打印一次时间

1. scheduleAtFixedRate Demo
初始化延迟为5s,每3s为一个Period,程序内执行Sleep 2s和print的操作

 def testFixedRatePool(): Unit = {
    // 初始化延时线程池
    val executor =  Executors.newScheduledThreadPool(3)
    val initDelay = 5
 
    // period执行任务
    executor.scheduleAtFixedRate(new Runnable {
      override def run(): Unit = {
        try {
          Thread.sleep(2000)
          println("Runnable Execute Success!")
        } catch {
          case e: Exception => {}
            e.printStackTrace()
        }
      }
    }, initDelay, 3, TimeUnit.SECONDS)
 
   executor.scheduleAtFixedRate(new Runnable {
     override def run(): Unit = {
       println("A second passed...")
     }
   }, 0, 1, TimeUnit.SECONDS)
 
  }


执行结果:

延时初始化用掉了5s,period 3s的前2s Sleep 然后打印,随后空闲1s,接下来到达新的period,依次往复

 

2. scheduleWithFixedDelay Demo
延时初始化5s,执行Runnable耗时约2s,打印标记信息,随后delay延时3s,循环往复

 

 def testFixedDelayPool(): Unit = {
    val executor =  Executors.newScheduledThreadPool(3)
    val initDelay = 5
    executor.scheduleWithFixedDelay(new Runnable {
      override def run(): Unit = {
        try {
          Thread.sleep(2000)
          println("Runnable Execute Success!")
        } catch {
          case e: Exception => {}
            e.printStackTrace()
        }
      }
    }, initDelay, 3, TimeUnit.SECONDS)
 
    executor.scheduleWithFixedDelay(new Runnable {
      override def run(): Unit = {
        println("A second passed...")
      }
    }, 0, 1, TimeUnit.SECONDS)
  }

执行结果:同上,延时初始化用掉了5s,执行Runnable 消耗2s,随后delay 3s,继续执行Runnable 消耗2s,delay 3s,依次往复

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值