6 |
|
|
7 |
|
package java.util.concurrent; |
8 |
|
import static java.util.concurrent.TimeUnit.NANOSECONDS; |
9 |
+ |
import static java.util.concurrent.TimeUnit.MILLISECONDS; |
10 |
|
import java.util.concurrent.atomic.AtomicLong; |
11 |
|
import java.util.concurrent.locks.Condition; |
12 |
|
import java.util.concurrent.locks.ReentrantLock; |
14 |
|
|
15 |
|
/** |
16 |
|
* A {@link ThreadPoolExecutor} that can additionally schedule |
17 |
< |
* commands to run after a given delay, or to execute |
18 |
< |
* periodically. This class is preferable to {@link java.util.Timer} |
19 |
< |
* when multiple worker threads are needed, or when the additional |
20 |
< |
* flexibility or capabilities of {@link ThreadPoolExecutor} (which |
21 |
< |
* this class extends) are required. |
17 |
> |
* commands to run after a given delay, or to execute periodically. |
18 |
> |
* This class is preferable to {@link java.util.Timer} when multiple |
19 |
> |
* worker threads are needed, or when the additional flexibility or |
20 |
> |
* capabilities of {@link ThreadPoolExecutor} (which this class |
21 |
> |
* extends) are required. |
22 |
|
* |
23 |
|
* <p>Delayed tasks execute no sooner than they are enabled, but |
24 |
|
* without any real-time guarantees about when, after they are |
27 |
|
* submission. |
28 |
|
* |
29 |
|
* <p>When a submitted task is cancelled before it is run, execution |
30 |
< |
* is suppressed. By default, such a cancelled task is not |
31 |
< |
* automatically removed from the work queue until its delay |
32 |
< |
* elapses. While this enables further inspection and monitoring, it |
33 |
< |
* may also cause unbounded retention of cancelled tasks. To avoid |
34 |
< |
* this, set {@link #setRemoveOnCancelPolicy} to {@code true}, which |
35 |
< |
* causes tasks to be immediately removed from the work queue at |
35 |
< |
* time of cancellation. |
30 |
> |
* is suppressed. By default, such a cancelled task is not |
31 |
> |
* automatically removed from the work queue until its delay elapses. |
32 |
> |
* While this enables further inspection and monitoring, it may also |
33 |
> |
* cause unbounded retention of cancelled tasks. To avoid this, use |
34 |
> |
* {@link #setRemoveOnCancelPolicy} to cause tasks to be immediately |
35 |
> |
* removed from the work queue at time of cancellation. |
36 |
|
* |
37 |
< |
* <p>Successive executions of a task scheduled via |
38 |
< |
* {@code scheduleAtFixedRate} or |
39 |
< |
* {@code scheduleWithFixedDelay} do not overlap. While different |
37 |
> |
* <p>Successive executions of a periodic task scheduled via |
38 |
> |
* {@link #scheduleAtFixedRate} or |
39 |
> |
* {@link #scheduleWithFixedDelay} do not overlap. While different |
40 |
|
* executions may be performed by different threads, the effects of |
41 |
|
* prior executions <a |
42 |
|
* href="package-summary.html#MemoryVisibility"><i>happen-before</i></a> |
131 |
|
private volatile boolean executeExistingDelayedTasksAfterShutdown = true; |
132 |
|
|
133 |
|
/** |
134 |
< |
* True if ScheduledFutureTask.cancel should remove from queue |
134 |
> |
* True if ScheduledFutureTask.cancel should remove from queue. |
135 |
|
*/ |
136 |
|
private volatile boolean removeOnCancel = false; |
137 |
|
|
158 |
|
private long time; |
159 |
|
|
160 |
|
/** |
161 |
< |
* Period in nanoseconds for repeating tasks. A positive |
162 |
< |
* value indicates fixed-rate execution. A negative value |
163 |
< |
* indicates fixed-delay execution. A value of 0 indicates a |
164 |
< |
* non-repeating task. |
161 |
> |
* Period in nanoseconds for repeating tasks. |
162 |
> |
* A positive value indicates fixed-rate execution. |
163 |
> |
* A negative value indicates fixed-delay execution. |
164 |
> |
* A value of 0 indicates a non-repeating (one-shot) task. |
165 |
|
*/ |
166 |
|
private final long period; |
167 |
|
|
176 |
|
/** |
177 |
|
* Creates a one-shot action with given nanoTime-based trigger time. |
178 |
|
*/ |
179 |
< |
ScheduledFutureTask(Runnable r, V result, long ns) { |
179 |
> |
ScheduledFutureTask(Runnable r, V result, long triggerTime) { |
180 |
|
super(r, result); |
181 |
< |
this.time = ns; |
181 |
> |
this.time = triggerTime; |
182 |
|
this.period = 0; |
183 |
|
this.sequenceNumber = sequencer.getAndIncrement(); |
184 |
|
} |
185 |
|
|
186 |
|
/** |
187 |
< |
* Creates a periodic action with given nano time and period. |
187 |
> |
* Creates a periodic action with given nanoTime-based initial |
188 |
> |
* trigger time and period. |
189 |
|
*/ |
190 |
< |
ScheduledFutureTask(Runnable r, V result, long ns, long period) { |
190 |
> |
ScheduledFutureTask(Runnable r, V result, long triggerTime, |
191 |
> |
long period) { |
192 |
|
super(r, result); |
193 |
< |
this.time = ns; |
193 |
> |
this.time = triggerTime; |
194 |
|
this.period = period; |
195 |
|
this.sequenceNumber = sequencer.getAndIncrement(); |
196 |
|
} |
198 |
|
/** |
199 |
|
* Creates a one-shot action with given nanoTime-based trigger time. |
200 |
|
*/ |
201 |
< |
ScheduledFutureTask(Callable<V> callable, long ns) { |
201 |
> |
ScheduledFutureTask(Callable<V> callable, long triggerTime) { |
202 |
|
super(callable); |
203 |
< |
this.time = ns; |
203 |
> |
this.time = triggerTime; |
204 |
|
this.period = 0; |
205 |
|
this.sequenceNumber = sequencer.getAndIncrement(); |
206 |
|
} |
392 |
|
} |
393 |
|
|
394 |
|
/** |
395 |
+ |
* The default keep-alive time for pool threads. |
396 |
+ |
* |
397 |
+ |
* Normally, this value is unused because all pool threads will be |
398 |
+ |
* core threads, but if a user creates a pool with a corePoolSize |
399 |
+ |
* of zero (against our advice), we keep a thread alive as long as |
400 |
+ |
* there are queued tasks. If the keep alive time is zero (the |
401 |
+ |
* historic value), we end up hot-spinning in getTask, wasting a |
402 |
+ |
* CPU. But on the other hand, if we set the value too high, and |
403 |
+ |
* users create a one-shot pool which they don't cleanly shutdown, |
404 |
+ |
* the pool's non-daemon threads will prevent JVM termination. A |
405 |
+ |
* small but non-zero value (relative to a JVM's lifetime) seems |
406 |
+ |
* best. |
407 |
+ |
*/ |
408 |
+ |
private static final long DEFAULT_KEEPALIVE_MILLIS = 10L; |
409 |
+ |
|
410 |
+ |
/** |
411 |
|
* Creates a new {@code ScheduledThreadPoolExecutor} with the |
412 |
|
* given core pool size. |
413 |
|
* |
416 |
|
* @throws IllegalArgumentException if {@code corePoolSize < 0} |
417 |
|
*/ |
418 |
|
public ScheduledThreadPoolExecutor(int corePoolSize) { |
419 |
< |
super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS, |
419 |
> |
super(corePoolSize, Integer.MAX_VALUE, |
420 |
> |
DEFAULT_KEEPALIVE_MILLIS, MILLISECONDS, |
421 |
|
new DelayedWorkQueue()); |
422 |
|
} |
423 |
|
|
434 |
|
*/ |
435 |
|
public ScheduledThreadPoolExecutor(int corePoolSize, |
436 |
|
ThreadFactory threadFactory) { |
437 |
< |
super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS, |
437 |
> |
super(corePoolSize, Integer.MAX_VALUE, |
438 |
> |
DEFAULT_KEEPALIVE_MILLIS, MILLISECONDS, |
439 |
|
new DelayedWorkQueue(), threadFactory); |
440 |
|
} |
441 |
|
|
442 |
|
/** |
443 |
< |
* Creates a new ScheduledThreadPoolExecutor with the given |
444 |
< |
* initial parameters. |
443 |
> |
* Creates a new {@code ScheduledThreadPoolExecutor} with the |
444 |
> |
* given initial parameters. |
445 |
|
* |
446 |
|
* @param corePoolSize the number of threads to keep in the pool, even |
447 |
|
* if they are idle, unless {@code allowCoreThreadTimeOut} is set |
452 |
|
*/ |
453 |
|
public ScheduledThreadPoolExecutor(int corePoolSize, |
454 |
|
RejectedExecutionHandler handler) { |
455 |
< |
super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS, |
455 |
> |
super(corePoolSize, Integer.MAX_VALUE, |
456 |
> |
DEFAULT_KEEPALIVE_MILLIS, MILLISECONDS, |
457 |
|
new DelayedWorkQueue(), handler); |
458 |
|
} |
459 |
|
|
460 |
|
/** |
461 |
< |
* Creates a new ScheduledThreadPoolExecutor with the given |
462 |
< |
* initial parameters. |
461 |
> |
* Creates a new {@code ScheduledThreadPoolExecutor} with the |
462 |
> |
* given initial parameters. |
463 |
|
* |
464 |
|
* @param corePoolSize the number of threads to keep in the pool, even |
465 |
|
* if they are idle, unless {@code allowCoreThreadTimeOut} is set |
474 |
|
public ScheduledThreadPoolExecutor(int corePoolSize, |
475 |
|
ThreadFactory threadFactory, |
476 |
|
RejectedExecutionHandler handler) { |
477 |
< |
super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS, |
477 |
> |
super(corePoolSize, Integer.MAX_VALUE, |
478 |
> |
DEFAULT_KEEPALIVE_MILLIS, MILLISECONDS, |
479 |
|
new DelayedWorkQueue(), threadFactory, handler); |
480 |
|
} |
481 |
|
|
482 |
|
/** |
483 |
< |
* Returns the trigger time of a delayed action. |
483 |
> |
* Returns the nanoTime-based trigger time of a delayed action. |
484 |
|
*/ |
485 |
|
private long triggerTime(long delay, TimeUnit unit) { |
486 |
|
return triggerTime(unit.toNanos((delay < 0) ? 0 : delay)); |
487 |
|
} |
488 |
|
|
489 |
|
/** |
490 |
< |
* Returns the trigger time of a delayed action. |
490 |
> |
* Returns the nanoTime-based trigger time of a delayed action. |
491 |
|
*/ |
492 |
|
long triggerTime(long delay) { |
493 |
|
return now() + |
520 |
|
TimeUnit unit) { |
521 |
|
if (command == null || unit == null) |
522 |
|
throw new NullPointerException(); |
523 |
< |
RunnableScheduledFuture<?> t = decorateTask(command, |
523 |
> |
RunnableScheduledFuture<Void> t = decorateTask(command, |
524 |
|
new ScheduledFutureTask<Void>(command, null, |
525 |
|
triggerTime(delay, unit))); |
526 |
|
delayedExecute(t); |
769 |
|
* fails to respond to interrupts may never terminate. |
770 |
|
* |
771 |
|
* @return list of tasks that never commenced execution. |
772 |
< |
* Each element of this list is a {@link ScheduledFuture}, |
773 |
< |
* including those tasks submitted using {@code execute}, |
774 |
< |
* which are for scheduling purposes used as the basis of a |
775 |
< |
* zero-delay {@code ScheduledFuture}. |
772 |
> |
* Each element of this list is a {@link ScheduledFuture}. |
773 |
> |
* For tasks submitted via one of the {@code schedule} |
774 |
> |
* methods, the element will be identical to the returned |
775 |
> |
* {@code ScheduledFuture}. For tasks submitted using |
776 |
> |
* {@link #execute}, the element will be a zero-delay {@code |
777 |
> |
* ScheduledFuture}. |
778 |
|
* @throws SecurityException {@inheritDoc} |
779 |
|
*/ |
780 |
|
public List<Runnable> shutdownNow() { |
782 |
|
} |
783 |
|
|
784 |
|
/** |
785 |
< |
* Returns the task queue used by this executor. Each element of |
786 |
< |
* this queue is a {@link ScheduledFuture}, including those |
787 |
< |
* tasks submitted using {@code execute} which are for scheduling |
788 |
< |
* purposes used as the basis of a zero-delay |
789 |
< |
* {@code ScheduledFuture}. Iteration over this queue is |
790 |
< |
* <em>not</em> guaranteed to traverse tasks in the order in |
791 |
< |
* which they will execute. |
785 |
> |
* Returns the task queue used by this executor. |
786 |
> |
* Each element of this list is a {@link ScheduledFuture}. |
787 |
> |
* For tasks submitted via one of the {@code schedule} methods, the |
788 |
> |
* element will be identical to the returned {@code ScheduledFuture}. |
789 |
> |
* For tasks submitted using {@link #execute}, the element will be a |
790 |
> |
* zero-delay {@code ScheduledFuture}. |
791 |
> |
* |
792 |
> |
* <p>Iteration over this queue is <em>not</em> guaranteed to traverse |
793 |
> |
* tasks in the order in which they will execute. |
794 |
|
* |
795 |
|
* @return the task queue |
796 |
|
*/ |
1250 |
|
* Snapshot iterator that works off copy of underlying q array. |
1251 |
|
*/ |
1252 |
|
private class Itr implements Iterator<Runnable> { |
1253 |
< |
final RunnableScheduledFuture[] array; |
1253 |
> |
final RunnableScheduledFuture<?>[] array; |
1254 |
|
int cursor = 0; // index of next element to return |
1255 |
|
int lastRet = -1; // index of last element, or -1 if no such |
1256 |
|
|
1257 |
< |
Itr(RunnableScheduledFuture[] array) { |
1257 |
> |
Itr(RunnableScheduledFuture<?>[] array) { |
1258 |
|
this.array = array; |
1259 |
|
} |
1260 |
|
|