ScheduledThreadPoolExecutor类的overflowFree方法overflowFree方法的源代码如下所示:
private long overflowFree(long delay) { //获取队列中的节点 Delayed head = (Delayed) super.getQueue().peek(); //获取的节点不为空 , 则进行后续处理 if (head != null) { //从队列节点中获取延迟时间 long headDelay = head.getDelay(NANOSECONDS); //如果从队列中获取的延迟时间小于0 , 并且传递的delay //值减去从队列节点中获取延迟时间小于0 if (headDelay < 0 && (delay - headDelay < 0)) //将delay的值设置为Long.MAX_VALUE + headDelay delay = Long.MAX_VALUE + headDelay; } //返回延迟时间 return delay;}通过对overflowFree方法的源码分析 , 可以看出overflowFree方法本质上就是为了限制队列中的所有节点的延迟时间在Long.MAX_VALUE值之内 , 防止在compareTo方法中溢出 。
cancel方法cancel方法的作用主要是取消当前任务的执行 , 源码如下所示:
public boolean cancel(boolean mayInterruptIfRunning) { //取消任务 , 返回任务是否取消的标识 boolean cancelled = super.cancel(mayInterruptIfRunning); //如果任务已经取消 //并且需要将任务从延迟队列中删除 //并且任务在延迟队列中的索引大于或者等于0 if (cancelled && removeOnCancel && heapIndex >= 0) //将当前任务从延迟队列中删除 remove(this); //返回是否成功取消任务的标识 return cancelled;}这段代码理解起来相对比较简单 , 首先调用取消任务的方法 , 并返回任务是否已经取消的标识 。如果任务已经取消 , 并且需要移除任务 , 同时 , 任务在延迟队列中的索引大于或者等于0 , 则将当前任务从延迟队列中移除 。最后返回任务是否成功取消的标识 。
run方法run方法可以说是ScheduledFutureTask类的核心方法 , 是对Runnable接口的实现 , 源码如下所示:
public void run() { //当前任务是否是周期性任务 boolean periodic = isPeriodic(); //线程池当前运行状态下不能执行周期性任务 if (!canRunInCurrentRunState(periodic)) //取消任务的执行 cancel(false); //如果不是周期性任务 else if (!periodic) //则直接调用FutureTask类的run方法执行任务 ScheduledFutureTask.super.run(); //如果是周期性任务 , 则调用FutureTask类的runAndReset方法执行任务 //如果任务执行成功 else if (ScheduledFutureTask.super.runAndReset()) { //设置下次执行任务的时间 setNextRunTime(); //重复执行任务 reExecutePeriodic(outerTask); }}整理一下方法的逻辑:
- 首先判断当前任务是否是周期性任务 。如果线程池当前运行状态下不能执行周期性任务 , 则取消任务的执行 , 否则执行步骤2;
- 如果当前任务不是周期性任务 , 则直接调用FutureTask类的run方法执行任务 , 会设置执行结果 , 然后直接返回 , 否则执行步骤3;
- 如果当前任务是周期性任务 , 则调用FutureTask类的runAndReset方法执行任务 , 不会设置执行结果 , 然后直接返回 , 否则执行步骤4;
- 如果任务执行成功 , 则设置下次执行任务的时间 , 同时 , 将任务设置为重复执行 。
这里 , 调用了FutureTask类的run方法和runAndReset方法 , 并且调用了ScheduledThreadPoolExecutor类的reExecutePeriodic方法 。接下来 , 我们分别看下这些方法的实现 。FutureTask类的run方法FutureTask类的run方法源码如下所示:
public void run() { //状态如果不是NEW , 说明任务或者已经执行过 , 或者已经被取消 , 直接返回 //状态如果是NEW , 则尝试把当前执行线程保存在runner字段中 //如果赋值失败则直接返回 if (state != NEW || !UNSAFE.compareAndSwapObject(this, runnerOffset, null, Thread.currentThread())) return; try { Callable<V> c = callable; if (c != null && state == NEW) { V result; boolean ran; try { //执行任务 result = c.call(); ran = true; } catch (Throwable ex) { result = null; ran = false; //任务异常 setException(ex); } if (ran) //任务正常执行完毕 set(result); } } finally { runner = null; int s = state; //如果任务被中断 , 执行中断处理 if (s >= INTERRUPTING) handlePossibleCancellationInterrupt(s); }}
推荐阅读
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 富春山居图是中国十大传名画之一这幅画的作者是 富春山居图是中国十大传世名画之一这幅画的作者是什么
- 古代寒门科举之路 没有科举之前都怎么当官的
- 班盆之美可比之班章,大滇号701批六星贺开
- 张仪得五寸退二寸之谋 张仪三寸不烂之舌纵横六国
- 英雄无用武之地的意思解释 形容英雄无用武之地的词语
- 绿茶之采花毛尖,采花毛尖价格预测
- 武则天在位多少年怎么退位的 武则天退位之后还活了多久
- |当了领导之后才明白的三个道理
- 胎儿男女双顶径对照表
- 康熙用人之术 康熙的用人之道
