用来执行延迟任务或者定时任务
它接受ScheduledFutureTask类型的任务,是线程池调度任务的最小单位。
它采用DelayQueue存储等待的任务
- DeplayQueue内部封装一个PriorityQueue,他会根据time的先后时间排序,如果time相同则根据sequenceNumber排序;
- DelayQueue是一个无界队列
Timer – 单线程,如果某一个Task出现问题,剩余所有Task都不会被执行。
ScheduledThreadPoolExecutor – 多线程,某一个task出现问题,剩余task不会受到影响。
ScheduledFutureTask
工作线程的执行过程
- 工作线程会从DelayQueue取已经到期的任务去执行;
- 执行结束后重新设置任务的到期时间,再放回DelayQueue
ScheduledThreadPoolExecutor会把待执行的任务放到工作队列DelayQueue中,使用compareTo方法进行排序。
- 首先按照time排序,time小的在前,大的在后;
- 如果时间相同,按照sequenceNumber排序,优先执行先提交的task。
run方法
线程池任务的提交
- schedule
- scheduledAtFixedRate
- scheduledWithFixedDelay
- schedule
任务在指定延迟时间到达后触发,只会执行一次
DelayedWorkQueue
基于堆的结构,类似于DelayQueue和PiorityQueue。在执行定时任务的时候,每个任务需要被执行的时间不同,所以DelayedWorkQueue就是将任务按执行时间的升序来排列。
Leader-Follower模式
所有线程会是三种身份中的一种:leader和follower还有干活中的状态:processor。他的基本元素就是,永远最多只有一个leader。所有follower都在等待成为leader。
线程池启动时会自动产生一个Leader负责等待网络IO事件,当有一个事件产生时,Leader线程首先通知Follower线程将其提拔为新的Leader,然后自己继续处理事件,处理完毕以后进入Follower线程等待队列,等待下一次成为Leader。
循环的根据key节点的值与他的parent来判断,如果小于父节点则两个节点交换。
take()
在take方法中,要保证只有在到指定的执行时间的时候任务才可以被取走。否则一直在队列中等待。
Leader的作用:减少不必要的定时等待,当一个线程成为leader时,他只等待下一个节点的时间间隔,但其他线程无限期等待。Leader线程必须在从take()返回之前signal其他线程,除非其他线程成为了leader。所以为了不让多个线程频繁的做无用的定时等待。
poll方法