通过源码可以看到 , 在ScheduledFutureTask类的构造方法中 , 首先会调用FutureTask类的构造方法为FutureTask类的callable和state成员变量赋值 , 接下来为ScheduledFutureTask类的time、period和sequenceNumber成员变量赋值 。理解起来比较简单 。
getDelay方法我们先来看getDelay方法的源码 , 如下所示:
//获取下次执行任务的时间距离当前时间的纳秒数public long getDelay(TimeUnit unit) { return unit.convert(time - now(), NANOSECONDS);}getDelay方法比较简单 , 主要用来获取下次执行任务的时间距离当前系统时间的纳秒数 。
compareTo方法ScheduledFutureTask类在类的结构上实现了Comparable接口 , compareTo方法主要是对Comparable接口定义的compareTo方法的实现 。源码如下所示:
public int compareTo(Delayed other) { if (other == this) return 0; if (other instanceof ScheduledFutureTask) { ScheduledFutureTask<?> x = (ScheduledFutureTask<?>)other; long diff = time - x.time; if (diff < 0) return -1; else if (diff > 0) return 1; else if (sequenceNumber < x.sequenceNumber) return -1; else return 1; } long diff = getDelay(NANOSECONDS) - other.getDelay(NANOSECONDS); return (diff < 0) ? -1 : (diff > 0) ? 1 : 0;}这段代码看上去好像是对各种数值类型数据的比较 , 本质上是对延迟队列中的任务进行排序 。排序规则为:
- 首先比较延迟队列中每个任务下次执行的时间 , 下次执行时间距离当前时间短的任务会排在前面;
- 如果下次执行任务的时间相同 , 则会比较任务的sequenceNumber值 , sequenceNumber值小的任务会排在前面 。
//判断是否是周期性任务public boolean isPeriodic() { return period != 0;}这个方法主要是用来判断当前任务是否是周期性任务 。这里只要判断运行任务的执行周期不等于0就能确定为周期性任务了 。因为无论period的值是大于0还是小于0 , 当前任务都是周期性任务 。setNextRunTime方法setNextRunTime方法的作用主要是设置当前任务下次执行的时间 , 源码如下所示:
private void setNextRunTime() { long p = period; //固定频率 , 上次执行任务的时间加上任务的执行周期 if (p > 0) time += p; //相对固定的延迟执行 , 当前系统时间加上任务的执行周期 else time = triggerTime(-p);}这里再一次证明了使用isPeriodic方法判断当前任务是否为周期性任务时 , 只要判断period的值是否不等于0就可以了 。- 因为如果当前任务时固定频率执行的周期性任务 , 会将周期period当作正数来处理;
- 如果是相对固定的延迟执行当前任务 , 则会将周期period当作负数来处理 。
ScheduledThreadPoolExecutor类的triggerTime方法triggerTime方法用于获取延迟队列中的任务下一次执行的具体时间 。源码如下所示 。
private long triggerTime(long delay, TimeUnit unit) { return triggerTime(unit.toNanos((delay < 0) ? 0 : delay));}long triggerTime(long delay) { return now() + ((delay < (Long.MAX_VALUE >> 1)) ? delay : overflowFree(delay));}这两个triggerTime方法的代码比较简单 , 就是获取下一次执行任务的具体时间 。有一点需要注意的是:delay < (Long.MAX_VALUE >> 1判断delay的值是否小于Long.MAX_VALUE的一半 , 如果小于Long.MAX_VALUE值的一半 , 则直接返回delay , 否则需要处理溢出的情况 。我们看到在triggerTime方法中处理防止溢出的逻辑使用了ScheduledThreadPoolExecutor类的overflowFree方法 , 接下来 , 我们就看看ScheduledThreadPoolExecutor类的overflowFree方法的实现 。
推荐阅读
- 富春山居图是中国十大传名画之一这幅画的作者是 富春山居图是中国十大传世名画之一这幅画的作者是什么
- 古代寒门科举之路 没有科举之前都怎么当官的
- 班盆之美可比之班章,大滇号701批六星贺开
- 张仪得五寸退二寸之谋 张仪三寸不烂之舌纵横六国
- 英雄无用武之地的意思解释 形容英雄无用武之地的词语
- 绿茶之采花毛尖,采花毛尖价格预测
- 武则天在位多少年怎么退位的 武则天退位之后还活了多久
- |当了领导之后才明白的三个道理
- 胎儿男女双顶径对照表
- 康熙用人之术 康熙的用人之道
