上篇文章我们讲解了Timer的实现机制,但是Timer定时器是单线程的,如果该线程终止的话,那么定时任务将无法执行,为此jdk1.5后推出了ScheduledThreadPoolExecutor,用于执行定时任务,为此我们在这里就分析一下ScheduledThreadPoolExecutor的具体实现么,因为ScheduledThreadPoolExecutor是基于ThreadPoolExecutor开发,所以请确保你有ThreadPoolExecutor的源码阅读经验,这里给大家推荐一篇大牛写的好文章https://www.cnblogs.com/trust-freedom/p/6594270.html,如果涉及到线程池我会带过,你看这篇上面那篇文章就知道了,另外你也需要知道FutureTask的底层机制,这个可以看我的另一篇博客https://blog.csdn.net/qq_32459653/article/details/81566639,这里面详细讲解了FutureTask的底层运行机制,有助于你理解ScheduledFutureTask是怎么工作的,应为它两为父子类关系。
package java.util.concurrent;
import static java.util.concurrent.TimeUnit.NANOSECONDS;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
import java.util.*;
public class ScheduledThreadPoolExecutor
extends ThreadPoolExecutor
implements ScheduledExecutorService {
/**
* 在shutdown后是否应该继续周期性任务 ture代表继续
*/
private volatile boolean continueExistingPeriodicTasksAfterShutdown;
/**
*
* 在shutdown后是否应该取消延迟任务 true代表取消
*/
private volatile boolean executeExistingDelayedTasksAfterShutdown = true;
/** ScheduledFutureTask状态为cancel是否应该移除,true代表是
* True if ScheduledFutureTask.cancel should remove from queue
*/
private volatile boolean removeOnCancel = false;
/**
* sequencer号生成器,每个ScheduledFutureTask,依靠sequencer生成序列号
* 如果不同的ScheduledFutureTask具有相同的执行时间,会优先执行序列号大的ScheduledFutureTask
*/
private static final AtomicLong sequencer = new AtomicLong();
/** 返回当前时间
* Returns current nanosecond time.
*/
final long now() {
return System.nanoTime();
}
//一个定时任务类,继承自futureTask,也意味着我们可以回去到执行结果
private class ScheduledFutureTask<V>
extends FutureTask<V> implements RunnableScheduledFuture<V> {
/*任务序列号 */
private final long sequenceNumber;
/** 任务可以被执行的时间 单位为 nanoTime units */
private long time;
/**
* 重复执行任务的周期,正数代表使用fixed-rate,负数代表fixed-delay,0代表不是重复任务
*/
private final long period;
/** 对于周期性执行任务而言 指向“ 外层”的任务,初始指向自身(默认),
*这里主要是由于decorateTask(由用户覆盖)可能会对本该任务“ 包装一番”
* outerTask会指向decorateTask的返回值,
*/
RunnableScheduledFuture<V> outerTask = this;
/** delay queue的索引,作用是支持快速删除,
* Index into delay queue, to support faster cancellation.
*/
int heapIndex;
/** 创建一个只指定触发时间只执行一次的ScheduledFutureTask任务,
* Creates a one-shot action with given nanoTime-based trigger time.
*/
ScheduledFutureTask(Runnable r, V result, long ns) {
super(r, result);
this.time = ns;
this.period = 0;
this.sequenceNumber = sequencer.getAndIncrement();
}
/** 创建一个给定指定延迟时间周期性执行的ScheduledFutureTask
* Creates a periodic action with given nano time and period.
*/
ScheduledFutureTask(Runnable r, V result, long ns, long period) {
super(r, result);
this.time = ns;
this.period = period;
this.sequenceNumber = sequencer.getAndIncrement();
}
/**
* 与上面类似,只不过过使用callable带返回结果
*/
ScheduledFutureTask(Callable<V> callable, long ns) {
super(callable);
this.time = ns;
this.period = 0;
this.sequenceNumber = sequencer.getAndIncrement();
}
//获取任务剩余的延迟时间,也就是还差多少时间执行,单位为NANOSECONDS
public long getDelay(TimeUnit unit) {
return unit.convert(time - now(), NANOSECONDS);
}
//用于比较两个ScheduledFutureTask执行时间的先后的大小,在被添加到DelayedWorkQueue的队列中被排序时将会被用到
public int compareTo(Delayed other) {
if (other == this) // compare zero if same object
return 0;
if (other instanceof ScheduledFutureTask) { // 是ScheduledFutureTask,则比较执行的时间
ScheduledFutureTask<?> x = (ScheduledFutureTask<?>)other;
long diff = time - x.time;
if (diff < 0) //小于返回-1
return -1;
else if (diff > 0) 大于返回1
return 1;
else if (sequenceNumber < x.sequenceNumber) //相等则比较sequenceNumber
return -1;
else
return 1;
}
//other不是ScheduledFutureTask型,则直接比较下次距离下次执行时间的大小
long diff = getDelay(NANOSECONDS) - other.getDelay(NANOSECONDS);
return (diff < 0) ? -1 : (diff > 0) ? 1 : 0;
}
/**
*
*判断是否是周期性执行的任务,为0代表周期性执行
*
*/
public boolean isPeriodic() {
return period != 0;
}
/**
* 对于周期性执行的任务, 设置下次执行的时间
* 参数p大于0,在使用scheduleWithiFixedDelay,会取period的负数而scheduleAtFixedRate则取正数以此来控制
* 是相对时间执行周期,还是绝对时间执行, 对此有疑问可以看关于Timer源码的详解,里面对此解读的比较清晰
*/
private void setNextRunTime() {
long p = period;
if (p > 0) //p大于0说明是绝对时间,对应Timer里面的SchedlutAtFixedRate;
time += p;
else
time = triggerTime(-p); //p小于0说明是相对执行执行 对应Timer定时器里面的schedule
}
//取消任务
public boolean cancel(boolean mayInterruptIfRunning) {
boolean cancelled = super.cancel(mayInterruptIfRunning);
if (cancelled && removeOnCancel && heapIndex >= 0)
remove(this);
return cancelled;
}
/**
* 覆盖FutureTask原有的run,方法,线程池中的线程取出ScheduledFutureTask,就是就是调用此方法的
* 所以如果是周期性任务,会在此处重新加入任务队列
*/
public void run() {
boolean periodic = isPeriodic();
if (!canRunInCurrentRunState(periodic))//当先线程池处于不可运行的状态
cancel(false); //取消
else if (!periodic) //不是周期性任务
ScheduledFutureTask.super.run(); //
else if (ScheduledFutureTask.super.runAndReset()) { //运行
setNextRunTime(); //设置下次运行时间
reExecutePeriodic(outerTask); //将该任务加入到任务队列
}
}
}
/**
*
* 判断当前是否可以运行
*
* @param periodic true if this task periodic, false if delayed
*/
boolean canRunInCurrentRunState(boolean periodic) {//与文章首部设置的字段值有关,可参考值的含义
return isRunningOrShutdown(periodic ?
continueExistingPeriodicTasksAfterShutdown :
executeExistingDelayedTasksAfterShutdown);
}
/**
* 该方法主要是针对延迟或者周期性执行的任务 ,如果线程池是shut down,将拒绝该任务,否则将添加到任务队列中,并启 * 动一个线程,
* @param task the task
*/
private void delayedExecute(RunnableScheduledFuture<?> task) {
if (isShutdown()) //关闭状态
reject(task); //拒接任务
else {
super.getQueue().add(task); //将任务添加到任务队列当中,会由线程池中的线程取出进行执行
if (isShutdown() &&
!canRunInCurrentRunState(task.isPeriodic()) &&
remove(task)) //如果线程池关闭,并且将canRunInCurrentRunStater返回false,remove成功,设置任务为取消状态
task.cancel(false);//取消任务
else
ensurePrestart(); //确保被加入到任务队列的任务执行完成,可以参考线程池的实现,也就是确保有一个线程在运行
}
}
/**
* 将周期性执行任务重新入队,
*
*
* @param task the task
*/
void reExecutePeriodic(RunnableScheduledFuture<?> task) {//
if (canRunInCurrentRunState(true)) {//如果当前线程池还处于可运行的状态,重新调度的必是周期任务,所以参数为true
super.getQueue().add(task); //加入的队列中
if (!canRunInCurrentRunState(true) && remove(task)) //
task.cancel(false);
else
ensurePrestart();
}
}
/**
*
*
*/
@Override void onShutdown() { //取消并清楚任务队里中的任务,并关闭线程池
BlockingQueue<Runnable> q = super.getQueue(); //获取任务队列
boolean keepDelayed =
getExecuteExistingDelayedTasksAfterShutdownPolicy();
boolean keepPeriodic =
getContinueExistingPeriodicTasksAfterShutdownPolicy();
if (!keepDelayed && !keepPeriodic) { //两个变量都为假,
for (Object e : q.toArray())
if (e instanceof RunnableScheduledFuture<?>)
((RunnableScheduledFuture<?>) e).cancel(false);
q.clear();
}
else {//有一个为真,说明即使调用onShutdown后,也允许部分任务执行,具体请看文章头部,介绍的属性值控制
// Traverse snapshot to avoid iterator exceptions
for (Object e : q.toArray()) {
if (e instanceof RunnableScheduledFuture) {
RunnableScheduledFuture<?> t =
(RunnableScheduledFuture<?>)e;
if ((t.isPeriodic() ? !keepPeriodic : !keepDelayed) || //如果t是周期性任务,则为 !keepPeriodic,否则为!keepDelayed ,
t.isCancelled()) { // also remove if already cancelled //在与t.isCancelled做或运算,以此来判断次任务是否应该被移除
if (q.remove(t))
t.cancel(false);
}
}
}
}
//尝试关闭线程池,请参考线程池源码解析
tryTerminate();
}
protected <V> RunnableScheduledFuture<V> decorateTask( //没有任务作用,可由用户覆盖,添加下自己的执行逻辑
Runnable runnable, RunnableScheduledFuture<V> task) {
return task;
}
protected <V> RunnableScheduledFuture<V> decorateTask( //没有任务作用,可由用户覆盖,添加下自己的执行逻辑
Callable<V> callable, RunnableScheduledFuture<V> task) {
return task;
}
public ScheduledThreadPoolExecutor(int corePoolSize) { //初始化线程池
super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS,
new DelayedWorkQueue());
}
//构造函数
public ScheduledThreadPoolExecutor(int corePoolSize,
ThreadFactory threadFactory) {
super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS,
new DelayedWorkQueue(), threadFactory);
}
//构造函数
public ScheduledThreadPoolExecutor(int corePoolSize,
RejectedExecutionHandler handler) {
super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS,
new DelayedWorkQueue(), handler);
}
//构造函数
public ScheduledThreadPoolExecutor(int corePoolSize,
ThreadFactory threadFactory,
RejectedExecutionHandler handler) {
super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS,
new DelayedWorkQueue(), threadFactory, handler);
/** //返回触发时间,具体看其重载的方法
* Returns the trigger time of a delayed action.
*/
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));
}
//说实话这个方法不太重要,主要是怕用户所设定的时间太长,而导致任务不能执行(比如几百年后)
//这里的细节部分我也没有深究,一般用不到,
private long overflowFree(long delay) {
Delayed head = (Delayed) super.getQueue().peek();
if (head != null) {
long headDelay = head.getDelay(NANOSECONDS);
if (headDelay < 0 && (delay - headDelay < 0))
delay = Long.MAX_VALUE + headDelay;
}
return delay;
}
/**
*
* //调用任务
*/
public ScheduledFuture<?> schedule(Runnable command,
long delay,
TimeUnit unit) {
if (command == null || unit == null) //为空?抛出异常
throw new NullPointerException();
//这里通过command构建一个RunnableScheduledFuture
//decorateTask,由用户覆盖(子类),可以对原有任务进行修改(装饰)
RunnableScheduledFuture<?> t = decorateTask(command,
new ScheduledFutureTask<Void>(command, null,
triggerTime(delay, unit)));
delayedExecute(t); //主要执行任务的函数,具体下面会分析
return t;
}
/**
*
* 与上面类型只不过上面是runnable
*/
public <V> ScheduledFuture<V> schedule(Callable<V> callable,
long delay,
TimeUnit unit) {
if (callable == null || unit == null)
throw new NullPointerException();
RunnableScheduledFuture<V> t = decorateTask(callable,
new ScheduledFutureTask<V>(callable,
triggerTime(delay, unit)));
delayedExecute(t); //
return t;
}
//以绝对时间周期性调度某任务,类似于Timer定时器的schedulaAtFixedRate调度
//其他方面都一样
public ScheduledFuture<?> scheduleAtFixedRate(Runnable command,
long initialDelay,
long period,
TimeUnit unit) {
if (command == null || unit == null)
throw new NullPointerException();
if (period <= 0)
throw new IllegalArgumentException();
ScheduledFutureTask<Void> sft =
new ScheduledFutureTask<Void>(command,
null,
triggerTime(initialDelay, unit),
unit.toNanos(period));
RunnableScheduledFuture<Void> t = decorateTask(command, sft);
sft.outerTask = t; //获取任务 sft的指向decorateTask返回值,由于默认什么都没做,这里指向自身
delayedExecute(t);//调度任务
return t;
}
/**
* 周期性相对时间执行某任务,类似Timer定时器里面的Schedule,
* @throws NullPointerException {@inheritDoc}
* @throws IllegalArgumentException {@inheritDoc}
*
public ScheduledFuture<?> scheduleWithFixedDelay(Runnable command,
long initialDelay,
long delay,
TimeUnit unit) {
if (command == null || unit == null)
throw new NullPointerException();
if (delay <= 0) //延后时间不能小于0,
throw new IllegalArgumentException();
ScheduledFutureTask<Void> sft =
new ScheduledFutureTask<Void>(command,
null,
triggerTime(initialDelay, unit),
unit.toNanos(-delay));
RunnableScheduledFuture<Void> t = decorateTask(command, sft);
sft.outerTask = t;
delayedExecute(t);
return t;
}
public void execute(Runnable command) { //执行任务,
schedule(command, 0, NANOSECONDS); //
}
// Override AbstractExecutorService methods
/**
* @throws RejectedExecutionException {@inheritDoc}
* @throws NullPointerException {@inheritDoc}
*/
public Future<?> submit(Runnable task) {
return schedule(task, 0, NANOSECONDS);
}
/**
* @throws RejectedExecutionException {@inheritDoc}
* @throws NullPointerException {@inheritDoc}
*/
public <T> Future<T> submit(Runnable task, T result) {
return schedule(Executors.callable(task, result), 0, NANOSECONDS);
}
/**
* @throws RejectedExecutionException {@inheritDoc}
* @throws NullPointerException {@inheritDoc}
*/
public <T> Future<T> submit(Callable<T> task) {
return schedule(task, 0, NANOSECONDS);
}
/**
* Sets the policy on whether to continue executing existing
* periodic tasks even when this executor has been {@code shutdown}.
* In this case, these tasks will only terminate upon
* {@code shutdownNow} or after setting the policy to
* {@code false} when already shutdown.
* This value is by default {@code false}.
*
* @param value if {@code true}, continue after shutdown, else don't
* @see #getContinueExistingPeriodicTasksAfterShutdownPolicy
*/
public void setContinueExistingPeriodicTasksAfterShutdownPolicy(boolean value) {
continueExistingPeriodicTasksAfterShutdown = value;
if (!value && isShutdown())
onShutdown();
}
/**
* Gets the policy on whether to continue executing existing
* periodic tasks even when this executor has been {@code shutdown}.
* In this case, these tasks will only terminate upon
* {@code shutdownNow} or after setting the policy to
* {@code false} when already shutdown.
* This value is by default {@code false}.
*
* @return {@code true} if will continue after shutdown
* @see #setContinueExistingPeriodicTasksAfterShutdownPolicy
*/
public boolean getContinueExistingPeriodicTasksAfterShutdownPolicy() {
return continueExistingPeriodicTasksAfterShutdown;
}
public void setExecuteExistingDelayedTasksAfterShutdownPolicy(boolean value) {
executeExistingDelayedTasksAfterShutdown = value;
if (!value && isShutdown())
onShutdown();
}
/**
* @return {@code true} if will execute after shutdown
* @see #setExecuteExistingDelayedTasksAfterShutdownPolicy
*/
public boolean getExecuteExistingDelayedTasksAfterShutdownPolicy() {
return executeExistingDelayedTasksAfterShutdown;
}
/**
* Sets the policy on whether cancelled tasks should be immediately
* removed from the work queue at time of cancellation. This value is
* by default {@code false}.
*
* @param value if {@code true}, remove on cancellation, else don't
* @see #getRemoveOnCancelPolicy
* @since 1.7
*/
public void setRemoveOnCancelPolicy(boolean value) {
removeOnCancel = value;
}
/**
* Gets the policy on whether cancelled tasks should be immediately
* removed from the work queue at time of cancellation. This value is
* by default {@code false}.
*
* @return {@code true} if cancelled tasks are immediately removed
* from the queue
* @see #setRemoveOnCancelPolicy
* @since 1.7
*/
public boolean getRemoveOnCancelPolicy() {
return removeOnCancel;
}
/**
* @throws SecurityException {@inheritDoc}
*/
public void shutdown() {
super.shutdown();
}
/**
* Attempts to stop all actively executing tasks, halts the
* processing of waiting tasks, and returns a list of the tasks
* that were awaiting execution.
*
* <p>This method does not wait for actively executing tasks to
* terminate. Use {@link #awaitTermination awaitTermination} to
* do that.
*
* <p>There are no guarantees beyond best-effort attempts to stop
* processing actively executing tasks. This implementation
* cancels tasks via {@link Thread#interrupt}, so any task that
* fails to respond to interrupts may never terminate.
*
* @return list of tasks that never commenced execution.
* Each element of this list is a {@link ScheduledFuture},
* including those tasks submitted using {@code execute},
* which are for scheduling purposes used as the basis of a
* zero-delay {@code ScheduledFuture}.
* @throws SecurityException {@inheritDoc}
*/
public List<Runnable> shutdownNow() {
return super.shutdownNow();
}
/**
* Returns the task queue used by this executor. Each element of
* this queue is a {@link ScheduledFuture}, including those
* tasks submitted using {@code execute} which are for scheduling
* purposes used as the basis of a zero-delay
* {@code ScheduledFuture}. Iteration over this queue is
* <em>not</em> guaranteed to traverse tasks in the order in
* which they will execute.
*
* @return the task queue
*/
public BlockingQueue<Runnable> getQueue() {
return super.getQueue();
}
//延迟任务队里,DelayQueue的变种,不知道DelayQueue,可以看看我对DelayQueue源码的详解
//其中该类里面涉及到了堆排序,这里对该算法就不做出详解了,一般程序员都会堆排序,不会的可要赶紧补!!
static class DelayedWorkQueue extends AbstractQueue<Runnable>
implements BlockingQueue<Runnable> {
//初始容量大小
private static final int INITIAL_CAPACITY = 16;
private RunnableScheduledFuture<?>[] queue =
new RunnableScheduledFuture<?>[INITIAL_CAPACITY];
private final ReentrantLock lock = new ReentrantLock();
private int size = 0;
//表明在该队列上等待的线程,主要是为了降低线程间锁竞争,
//一次,只有一个线程可以在该队列上取任务执行,
private Thread leader = null;
private final Condition available = lock.newCondition();
/**
* Sets f's heapIndex if it is a ScheduledFutureTask.
*/
private void setIndex(RunnableScheduledFuture<?> f, int idx) {
if (f instanceof ScheduledFutureTask)
((ScheduledFutureTask)f).heapIndex = idx;
}
//堆排序的变种 向上调整,堆排序涉及到的一部分,注意执行该操作前,请确保持有锁
private void siftUp(int k, RunnableScheduledFuture<?> key) {
while (k > 0) {
int parent = (k - 1) >>> 1;
RunnableScheduledFuture<?> e = queue[parent];
if (key.compareTo(e) >= 0)
break;
queue[k] = e;
setIndex(e, k);
k = parent;
}
queue[k] = key;
setIndex(key, k);
}
/**
* 向下调整,堆排序涉及到的一部分,注意执行该操作前,请确保持有锁
*
private void siftDown(int k, RunnableScheduledFuture<?> key) {
int half = size >>> 1;
while (k < half) {
int child = (k << 1) + 1;
RunnableScheduledFuture<?> c = queue[child];
int right = child + 1;
if (right < size && c.compareTo(queue[right]) > 0)
c = queue[child = right];
if (key.compareTo(c) <= 0)
break;
queue[k] = c;
setIndex(c, k);
k = child;
}
queue[k] = key;
setIndex(key, k);
}
/**
* 扩容操作,
*/
private void grow() {
int oldCapacity = queue.length;
int newCapacity = oldCapacity + (oldCapacity >> 1); // grow 50%
if (newCapacity < 0) // overflow
newCapacity = Integer.MAX_VALUE;
queue = Arrays.copyOf(queue, newCapacity);
}
/**
* Finds index of given object, or -1 if absent.
*/
private int indexOf(Object x) {
if (x != null) {
if (x instanceof ScheduledFutureTask) {
int i = ((ScheduledFutureTask) x).heapIndex;
// Sanity check; x could conceivably be a
// ScheduledFutureTask from some other pool.
if (i >= 0 && i < size && queue[i] == x)
return i;
} else {
for (int i = 0; i < size; i++)
if (x.equals(queue[i]))
return i;
}
}
return -1;
}
public boolean contains(Object x) {
final ReentrantLock lock = this.lock;
lock.lock();
try {
return indexOf(x) != -1;
} finally {
lock.unlock();
}
}
public boolean remove(Object x) {
final ReentrantLock lock = this.lock;
lock.lock();
try {
int i = indexOf(x);
if (i < 0)
return false;
setIndex(queue[i], -1);
int s = --size;
RunnableScheduledFuture<?> replacement = queue[s];
queue[s] = null;
if (s != i) {
siftDown(i, replacement);
if (queue[i] == replacement)
siftUp(i, replacement);
}
return true;
} finally {
lock.unlock();
}
}
public int size() {
final ReentrantLock lock = this.lock;
lock.lock();
try {
return size;
} finally {
lock.unlock();
}
}
public boolean isEmpty() {
return size() == 0;
}
public int remainingCapacity() {
return Integer.MAX_VALUE;
}
public RunnableScheduledFuture<?> peek() {
final ReentrantLock lock = this.lock;
lock.lock();
try {
return queue[0];
} finally {
lock.unlock();
}
}
public boolean offer(Runnable x) {
if (x == null)
throw new NullPointerException();
RunnableScheduledFuture<?> e = (RunnableScheduledFuture<?>)x;
final ReentrantLock lock = this.lock;
lock.lock();
try {
int i = size;
if (i >= queue.length)
grow();
size = i + 1;
if (i == 0) {
queue[0] = e;
setIndex(e, 0);
} else {
siftUp(i, e);
}
if (queue[0] == e) {
leader = null;
available.signal();
}
} finally {
lock.unlock();
}
return true;
}
public void put(Runnable e) {
offer(e);
}
public boolean add(Runnable e) {
return offer(e);
}
public boolean offer(Runnable e, long timeout, TimeUnit unit) {
return offer(e);
}
/**
* Performs common bookkeeping for poll and take: Replaces
* first element with last and sifts it down. Call only when
* holding lock.
* @param f the task to remove and return
*/
private RunnableScheduledFuture<?> finishPoll(RunnableScheduledFuture<?> f) {
int s = --size;
RunnableScheduledFuture<?> x = queue[s];
queue[s] = null;
if (s != 0)
siftDown(0, x);
setIndex(f, -1);
return f;
}
//任务出列,没哟返回空
public RunnableScheduledFuture<?> poll() {
final ReentrantLock lock = this.lock;
lock.lock();
try {
RunnableScheduledFuture<?> first = queue[0];
if (first == null || first.getDelay(NANOSECONDS) > 0)
return null;
else
return finishPoll(first);
} finally {
lock.unlock();
}
}
//弹出任务,没有阻塞
public RunnableScheduledFuture<?> take() throws InterruptedException {
final ReentrantLock lock = this.lock;
lock.lockInterruptibly();
try {
for (;;) {
RunnableScheduledFuture<?> first = queue[0];
if (first == null)
available.await();
else {
long delay = first.getDelay(NANOSECONDS);
if (delay <= 0) //小于0 立马出列,被执行
return finishPoll(first);
first = null; // don't retain ref while waiting
if (leader != null) //leader !=null,说明有线程在等待
available.await();
else { //为空,说明没有线程在等待
Thread thisThread = Thread.currentThread();
leader = thisThread;
try {
available.awaitNanos(delay); //等待指定时间后苏醒
} finally {
if (leader == thisThread) //leader等于当前线程,当前线程执行完成后,应将leader置为空
leader = null;
}
}
}
}
} finally {
if (leader == null && queue[0] != null)
available.signal(); //唤醒标志
lock.unlock();
}
}
public RunnableScheduledFuture<?> poll(long timeout, TimeUnit unit)
throws InterruptedException {
long nanos = unit.toNanos(timeout);
final ReentrantLock lock = this.lock;
lock.lockInterruptibly();
try {
for (;;) {
RunnableScheduledFuture<?> first = queue[0];
if (first == null) {
if (nanos <= 0)
return null;
else
nanos = available.awaitNanos(nanos);
} else {
long delay = first.getDelay(NANOSECONDS);
if (delay <= 0)
return finishPoll(first);
if (nanos <= 0)
return null;
first = null; // don't retain ref while waiting
if (nanos < delay || leader != null)
nanos = available.awaitNanos(nanos);
else {
Thread thisThread = Thread.currentThread();
leader = thisThread;
try {
long timeLeft = available.awaitNanos(delay);
nanos -= delay - timeLeft;
} finally {
if (leader == thisThread)
leader = null;
}
}
}
}
} finally {
if (leader == null && queue[0] != null)
available.signal();
lock.unlock();
}
}
public void clear() {
final ReentrantLock lock = this.lock;
lock.lock();
try {
for (int i = 0; i < size; i++) {
RunnableScheduledFuture<?> t = queue[i];
if (t != null) {
queue[i] = null;
setIndex(t, -1);
}
}
size = 0;
} finally {
lock.unlock();
}
}
/**
* Returns first element only if it is expired.
* Used only by drainTo. Call only when holding lock.
*/
private RunnableScheduledFuture<?> peekExpired() {
// assert lock.isHeldByCurrentThread();
RunnableScheduledFuture<?> first = queue[0];
return (first == null || first.getDelay(NANOSECONDS) > 0) ?
null : first;
}
public int drainTo(Collection<? super Runnable> c) {
if (c == null)
throw new NullPointerException();
if (c == this)
throw new IllegalArgumentException();
final ReentrantLock lock = this.lock;
lock.lock();
try {
RunnableScheduledFuture<?> first;
int n = 0;
while ((first = peekExpired()) != null) {
c.add(first); // In this order, in case add() throws.
finishPoll(first);
++n;
}
return n;
} finally {
lock.unlock();
}
}
public int drainTo(Collection<? super Runnable> c, int maxElements) {
if (c == null)
throw new NullPointerException();
if (c == this)
throw new IllegalArgumentException();
if (maxElements <= 0)
return 0;
final ReentrantLock lock = this.lock;
lock.lock();
try {
RunnableScheduledFuture<?> first;
int n = 0;
while (n < maxElements && (first = peekExpired()) != null) {
c.add(first); // In this order, in case add() throws.
finishPoll(first);
++n;
}
return n;
} finally {
lock.unlock();
}
}
public Object[] toArray() {
final ReentrantLock lock = this.lock;
lock.lock();
try {
return Arrays.copyOf(queue, size, Object[].class);
} finally {
lock.unlock();
}
}
@SuppressWarnings("unchecked")
public <T> T[] toArray(T[] a) {
final ReentrantLock lock = this.lock;
lock.lock();
try {
if (a.length < size)
return (T[]) Arrays.copyOf(queue, size, a.getClass());
System.arraycopy(queue, 0, a, 0, size);
if (a.length > size)
a[size] = null;
return a;
} finally {
lock.unlock();
}
}
public Iterator<Runnable> iterator() {
return new Itr(Arrays.copyOf(queue, size));
}
/**
* Snapshot iterator that works off copy of underlying q array.
*/
private class Itr implements Iterator<Runnable> {
final RunnableScheduledFuture<?>[] array;
int cursor = 0; // index of next element to return
int lastRet = -1; // index of last element, or -1 if no such
Itr(RunnableScheduledFuture<?>[] array) {
this.array = array;
}
public boolean hasNext() {
return cursor < array.length;
}
public Runnable next() {
if (cursor >= array.length)
throw new NoSuchElementException();
lastRet = cursor;
return array[cursor++];
}
public void remove() {
if (lastRet < 0)
throw new IllegalStateException();
DelayedWorkQueue.this.remove(array[lastRet]);
lastRet = -1;
}
}
}
}