第9章 Java并发包中ScheduledThreadPoolExecutor原理探究

9.1 介绍

ThreadPoolExecutor只是Executors工具类的一部分功能。下面来介绍另外一部分功能,也就是ScheduledThreadPoolExecutor的实现,这是一个可以在指定一定延迟时间后或者定时进行任务调度执行的线程池。

9.2 类图介绍

Executors其实是个工具类,它提供了好多静态方法,可根据用户的选择返回不同的线程池实例。ScheduledThreadPoolExecutor继承了ThreadPoolExecutor并实现了ScheduledExecutorService接口。线程池队列是DelayedWorkQueue,其和DelayedQueue类似,是一个延迟队列。

ScheduledFutureTask具有返回值的任务,继承自FutureTask。FutureTask的内部有一个变量state用来表示任务的状态,一开始状态为NEW,所有状态为

private static final int NEW          = 0;		// 初始状态
private static final int COMPLETING   = 1;		// 执行中状态
private static final int NORMAL       = 2;		// 正常运行结束状态
private static final int EXCEPTIONAL  = 3;		// 运行中异常
private static final int CANCELLED    = 4;		// 任务被取消
private static final int INTERRUPTING = 5;		// 任务正在被中断
private static final int INTERRUPTED  = 6;		// 任务已经被中断

// 可能的任务状态转换路径:
NEW -> COMPLETING -> NORMAL / /初始状态->执行中->正常结束
NEW -> COMPLETING -> EXCEPTIONAL/ /初始状态->执行中->执行异常
NEW -> CANCELLED/ /初始状态->任务取消
NEW -> INTERRUPTING -> INTERRUPTED/ /初始状态->被中断中->被中断

ScheduledFutureTask内部还有一个变量period用来表示任务的类型,任务类型如下:

  • period=0,说明当前任务是一次性的,执行完毕后就退出了
  • period为负数,说明当前任务为fixed-delay任务,是固定延迟的定时可重复执行任务。
  • period为正数,说明当前任务为fixed-rate任务,是固定频率的定时可重复执行任务。
9.3 原理剖析
  • schedule(Runnable command, long delay, TimeUnit unit):该方法的作用是提交一个延迟执行的任务,任务从提交时间算起延迟单位为unit的delay时间后开始执行。提交的任务不是周期性任务,任务只会执行一次。

  • scheduleWithFixedDelay(Runnable command, long initialDelay, long delay,TimeUnit unit):该方法的作用是,当任务执行完毕后,让其延迟固定时间后再次运行(fixed-delay任务)。其中initialDelay表示提交任务后延迟多少时间开始执行任务command, delay表示当任务执行完毕后延长多少时间后再次运行command任务,unitinitialDelaydelay的时间单位。任务会一直重复运行直到任务运行中抛出了异常,被取消了,或者关闭了线程池。

    当添加一个任务到延迟队列后,等待initialDelay时间,任务就会过期,过期的任务就会被从队列移除,并执行。执行完毕后,会重新设置任务的延迟时间,然后再把任务放入延迟队列,循环往复。需要注意的是,如果一个任务在执行中抛出了异常,那么这个任务就结束了,但是不影响其他任务的执行

    scheduledExecutorService.scheduleWithFixedDelay开始执行----Wed May 27 17:04:53 CST 2020  【FIRST】
    本次执行任务时间为3秒 
      
    scheduledExecutorService.scheduleWithFixedDelay开始执行----Wed May 27 17:04:58 CST 2020
    本次执行任务时间为5秒 
    scheduledExecutorService.scheduleWithFixedDelay开始执行----Wed May 27 17:05:05 CST 2020
    本次执行任务时间为1秒 
    scheduledExecutorService.scheduleWithFixedDelay开始执行----Wed May 27 17:05:08 CST 2020
    本次执行任务时间为2秒 
    scheduledExecutorService.scheduleWithFixedDelay开始执行----Wed May 27 17:05:12 CST 2020
    
  • scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnitunit)该方法相对起始时间点以固定频率调用指定的任务,当把任务提交到线程池并延迟initialDelay时间(时间单位为unit)后开始执行任务command。然后从initialDelay+period时间点再次执行,而后在initialDelay + 2 * period时间点再次执行,循环往复,直到抛出异常或者调用了任务的cancel方法取消了任务,或者关闭了线程池。

    相对于fixed-delay任务来说,fixed-rate方式执行规则为,时间为initdelday +n*period时启动任务,但是如果当前任务还没有执行完,下一次要执行任务的时间到了,则不会并发执行,下次要执行的任务会延迟执行,要等到当前任务执行完毕后再执行

    scheduledExecutorService.scheduleWithFixedDelay开始执行----Wed May 27 17:07:09 CST 2020		【FIRST】
    本次执行任务时间为5秒 
      
    scheduledExecutorService.scheduleWithFixedDelay开始执行----Wed May 27 17:07:14 CST 2020
    本次执行任务时间为4秒 
    scheduledExecutorService.scheduleWithFixedDelay开始执行----Wed May 27 17:07:18 CST 2020
    本次执行任务时间为4秒 
    scheduledExecutorService.scheduleWithFixedDelay开始执行----Wed May 27 17:07:22 CST 2020
    本次执行任务时间为2秒 
    scheduledExecutorService.scheduleWithFixedDelay开始执行----Wed May 27 17:07:24 CST 2020
    
9.4 总结

本章讲解了ScheduledThreadPoolExecutor的实现原理,ScheduledThreadPoolExecutor其内部使用DelayQueue来存放具体任务。任务分为三种,其中一次性执行任务执行完毕就结束了,fixed-delay任务保证同一个任务在多次执行之间间隔固定时间,fixed-rate任务保证按照固定的频率执行。任务类型使用period的值来区分。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值