blob: f0b1f42f2b174ef3ceeffa8668f22b12d853f81e [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
3 *
4 * This code is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License version 2 only, as
6 * published by the Free Software Foundation. Sun designates this
7 * particular file as subject to the "Classpath" exception as provided
8 * by Sun in the LICENSE file that accompanied this code.
9 *
10 * This code is distributed in the hope that it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 * version 2 for more details (a copy is included in the LICENSE file that
14 * accompanied this code).
15 *
16 * You should have received a copy of the GNU General Public License version
17 * 2 along with this work; if not, write to the Free Software Foundation,
18 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
19 *
20 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
21 * CA 95054 USA or visit www.sun.com if you need additional information or
22 * have any questions.
23 */
24
25/*
26 * This file is available under and governed by the GNU General Public
27 * License version 2 only, as published by the Free Software Foundation.
28 * However, the following notice accompanied the original version of this
29 * file:
30 *
31 * Written by Doug Lea with assistance from members of JCP JSR-166
32 * Expert Group and released to the public domain, as explained at
33 * http://creativecommons.org/licenses/publicdomain
34 */
35
36package java.util.concurrent;
37import java.util.concurrent.atomic.*;
38import java.util.*;
39
40/**
41 * A {@link ThreadPoolExecutor} that can additionally schedule
42 * commands to run after a given delay, or to execute
43 * periodically. This class is preferable to {@link java.util.Timer}
44 * when multiple worker threads are needed, or when the additional
45 * flexibility or capabilities of {@link ThreadPoolExecutor} (which
46 * this class extends) are required.
47 *
48 * <p> Delayed tasks execute no sooner than they are enabled, but
49 * without any real-time guarantees about when, after they are
50 * enabled, they will commence. Tasks scheduled for exactly the same
51 * execution time are enabled in first-in-first-out (FIFO) order of
52 * submission.
53 *
54 * <p>While this class inherits from {@link ThreadPoolExecutor}, a few
55 * of the inherited tuning methods are not useful for it. In
56 * particular, because it acts as a fixed-sized pool using
57 * {@code corePoolSize} threads and an unbounded queue, adjustments
58 * to {@code maximumPoolSize} have no useful effect. Additionally, it
59 * is almost never a good idea to set {@code corePoolSize} to zero or
60 * use {@code allowCoreThreadTimeOut} because this may leave the pool
61 * without threads to handle tasks once they become eligible to run.
62 *
63 * <p><b>Extension notes:</b> This class overrides the
64 * {@link ThreadPoolExecutor#execute execute} and
65 * {@link AbstractExecutorService#submit(Runnable) submit}
66 * methods to generate internal {@link ScheduledFuture} objects to
67 * control per-task delays and scheduling. To preserve
68 * functionality, any further overrides of these methods in
69 * subclasses must invoke superclass versions, which effectively
70 * disables additional task customization. However, this class
71 * provides alternative protected extension method
72 * {@code decorateTask} (one version each for {@code Runnable} and
73 * {@code Callable}) that can be used to customize the concrete task
74 * types used to execute commands entered via {@code execute},
75 * {@code submit}, {@code schedule}, {@code scheduleAtFixedRate},
76 * and {@code scheduleWithFixedDelay}. By default, a
77 * {@code ScheduledThreadPoolExecutor} uses a task type extending
78 * {@link FutureTask}. However, this may be modified or replaced using
79 * subclasses of the form:
80 *
81 * <pre> {@code
82 * public class CustomScheduledExecutor extends ScheduledThreadPoolExecutor {
83 *
84 * static class CustomTask<V> implements RunnableScheduledFuture<V> { ... }
85 *
86 * protected <V> RunnableScheduledFuture<V> decorateTask(
87 * Runnable r, RunnableScheduledFuture<V> task) {
88 * return new CustomTask<V>(r, task);
89 * }
90 *
91 * protected <V> RunnableScheduledFuture<V> decorateTask(
92 * Callable<V> c, RunnableScheduledFuture<V> task) {
93 * return new CustomTask<V>(c, task);
94 * }
95 * // ... add constructors, etc.
96 * }}</pre>
97 *
98 * @since 1.5
99 * @author Doug Lea
100 */
101public class ScheduledThreadPoolExecutor
102 extends ThreadPoolExecutor
103 implements ScheduledExecutorService {
104
105 /*
106 * This class specializes ThreadPoolExecutor implementation by
107 *
108 * 1. Using a custom task type, ScheduledFutureTask for
109 * tasks, even those that don't require scheduling (i.e.,
110 * those submitted using ExecutorService execute, not
111 * ScheduledExecutorService methods) which are treated as
112 * delayed tasks with a delay of zero.
113 *
114 * 2. Using a custom queue (DelayedWorkQueue) based on an
115 * unbounded DelayQueue. The lack of capacity constraint and
116 * the fact that corePoolSize and maximumPoolSize are
117 * effectively identical simplifies some execution mechanics
118 * (see delayedExecute) compared to ThreadPoolExecutor
119 * version.
120 *
121 * The DelayedWorkQueue class is defined below for the sake of
122 * ensuring that all elements are instances of
123 * RunnableScheduledFuture. Since DelayQueue otherwise
124 * requires type be Delayed, but not necessarily Runnable, and
125 * the workQueue requires the opposite, we need to explicitly
126 * define a class that requires both to ensure that users don't
127 * add objects that aren't RunnableScheduledFutures via
128 * getQueue().add() etc.
129 *
130 * 3. Supporting optional run-after-shutdown parameters, which
131 * leads to overrides of shutdown methods to remove and cancel
132 * tasks that should NOT be run after shutdown, as well as
133 * different recheck logic when task (re)submission overlaps
134 * with a shutdown.
135 *
136 * 4. Task decoration methods to allow interception and
137 * instrumentation, which are needed because subclasses cannot
138 * otherwise override submit methods to get this effect. These
139 * don't have any impact on pool control logic though.
140 */
141
142 /**
143 * False if should cancel/suppress periodic tasks on shutdown.
144 */
145 private volatile boolean continueExistingPeriodicTasksAfterShutdown;
146
147 /**
148 * False if should cancel non-periodic tasks on shutdown.
149 */
150 private volatile boolean executeExistingDelayedTasksAfterShutdown = true;
151
152 /**
153 * Sequence number to break scheduling ties, and in turn to
154 * guarantee FIFO order among tied entries.
155 */
156 private static final AtomicLong sequencer = new AtomicLong(0);
157
158 /**
159 * Returns current nanosecond time.
160 */
161 final long now() {
162 return System.nanoTime();
163 }
164
165 private class ScheduledFutureTask<V>
166 extends FutureTask<V> implements RunnableScheduledFuture<V> {
167
168 /** Sequence number to break ties FIFO */
169 private final long sequenceNumber;
170 /** The time the task is enabled to execute in nanoTime units */
171 private long time;
172 /**
173 * Period in nanoseconds for repeating tasks. A positive
174 * value indicates fixed-rate execution. A negative value
175 * indicates fixed-delay execution. A value of 0 indicates a
176 * non-repeating task.
177 */
178 private final long period;
179
180 /** The actual task to be re-enqueued by reExecutePeriodic */
181 RunnableScheduledFuture<V> outerTask = this;
182
183 /**
184 * Creates a one-shot action with given nanoTime-based trigger time.
185 */
186 ScheduledFutureTask(Runnable r, V result, long ns) {
187 super(r, result);
188 this.time = ns;
189 this.period = 0;
190 this.sequenceNumber = sequencer.getAndIncrement();
191 }
192
193 /**
194 * Creates a periodic action with given nano time and period.
195 */
196 ScheduledFutureTask(Runnable r, V result, long ns, long period) {
197 super(r, result);
198 this.time = ns;
199 this.period = period;
200 this.sequenceNumber = sequencer.getAndIncrement();
201 }
202
203 /**
204 * Creates a one-shot action with given nanoTime-based trigger.
205 */
206 ScheduledFutureTask(Callable<V> callable, long ns) {
207 super(callable);
208 this.time = ns;
209 this.period = 0;
210 this.sequenceNumber = sequencer.getAndIncrement();
211 }
212
213 public long getDelay(TimeUnit unit) {
214 long d = unit.convert(time - now(), TimeUnit.NANOSECONDS);
215 return d;
216 }
217
218 public int compareTo(Delayed other) {
219 if (other == this) // compare zero ONLY if same object
220 return 0;
221 if (other instanceof ScheduledFutureTask) {
222 ScheduledFutureTask<?> x = (ScheduledFutureTask<?>)other;
223 long diff = time - x.time;
224 if (diff < 0)
225 return -1;
226 else if (diff > 0)
227 return 1;
228 else if (sequenceNumber < x.sequenceNumber)
229 return -1;
230 else
231 return 1;
232 }
233 long d = (getDelay(TimeUnit.NANOSECONDS) -
234 other.getDelay(TimeUnit.NANOSECONDS));
235 return (d == 0) ? 0 : ((d < 0) ? -1 : 1);
236 }
237
238 /**
239 * Returns true if this is a periodic (not a one-shot) action.
240 *
241 * @return true if periodic
242 */
243 public boolean isPeriodic() {
244 return period != 0;
245 }
246
247 /**
248 * Sets the next time to run for a periodic task.
249 */
250 private void setNextRunTime() {
251 long p = period;
252 if (p > 0)
253 time += p;
254 else
255 time = now() - p;
256 }
257
258 /**
259 * Overrides FutureTask version so as to reset/requeue if periodic.
260 */
261 public void run() {
262 boolean periodic = isPeriodic();
263 if (!canRunInCurrentRunState(periodic))
264 cancel(false);
265 else if (!periodic)
266 ScheduledFutureTask.super.run();
267 else if (ScheduledFutureTask.super.runAndReset()) {
268 setNextRunTime();
269 reExecutePeriodic(outerTask);
270 }
271 }
272 }
273
274 /**
275 * Returns true if can run a task given current run state
276 * and run-after-shutdown parameters.
277 *
278 * @param periodic true if this task periodic, false if delayed
279 */
280 boolean canRunInCurrentRunState(boolean periodic) {
281 return isRunningOrShutdown(periodic ?
282 continueExistingPeriodicTasksAfterShutdown :
283 executeExistingDelayedTasksAfterShutdown);
284 }
285
286 /**
287 * Main execution method for delayed or periodic tasks. If pool
288 * is shut down, rejects the task. Otherwise adds task to queue
289 * and starts a thread, if necessary, to run it. (We cannot
290 * prestart the thread to run the task because the task (probably)
291 * shouldn't be run yet,) If the pool is shut down while the task
292 * is being added, cancel and remove it if required by state and
293 * run-after-shutdown parameters.
294 *
295 * @param task the task
296 */
297 private void delayedExecute(RunnableScheduledFuture<?> task) {
298 if (isShutdown())
299 reject(task);
300 else {
301 super.getQueue().add(task);
302 if (isShutdown() &&
303 !canRunInCurrentRunState(task.isPeriodic()) &&
304 remove(task))
305 task.cancel(false);
306 else
307 prestartCoreThread();
308 }
309 }
310
311 /**
312 * Requeues a periodic task unless current run state precludes it.
313 * Same idea as delayedExecute except drops task rather than rejecting.
314 *
315 * @param task the task
316 */
317 void reExecutePeriodic(RunnableScheduledFuture<?> task) {
318 if (canRunInCurrentRunState(true)) {
319 super.getQueue().add(task);
320 if (!canRunInCurrentRunState(true) && remove(task))
321 task.cancel(false);
322 else
323 prestartCoreThread();
324 }
325 }
326
327 /**
328 * Cancels and clears the queue of all tasks that should not be run
329 * due to shutdown policy. Invoked within super.shutdown.
330 */
331 @Override void onShutdown() {
332 BlockingQueue<Runnable> q = super.getQueue();
333 boolean keepDelayed =
334 getExecuteExistingDelayedTasksAfterShutdownPolicy();
335 boolean keepPeriodic =
336 getContinueExistingPeriodicTasksAfterShutdownPolicy();
337 if (!keepDelayed && !keepPeriodic)
338 q.clear();
339 else {
340 // Traverse snapshot to avoid iterator exceptions
341 for (Object e : q.toArray()) {
342 if (e instanceof RunnableScheduledFuture) {
343 RunnableScheduledFuture<?> t =
344 (RunnableScheduledFuture<?>)e;
345 if ((t.isPeriodic() ? !keepPeriodic : !keepDelayed) ||
346 t.isCancelled()) { // also remove if already cancelled
347 if (q.remove(t))
348 t.cancel(false);
349 }
350 }
351 }
352 }
353 tryTerminate();
354 }
355
356 /**
357 * Modifies or replaces the task used to execute a runnable.
358 * This method can be used to override the concrete
359 * class used for managing internal tasks.
360 * The default implementation simply returns the given task.
361 *
362 * @param runnable the submitted Runnable
363 * @param task the task created to execute the runnable
364 * @return a task that can execute the runnable
365 * @since 1.6
366 */
367 protected <V> RunnableScheduledFuture<V> decorateTask(
368 Runnable runnable, RunnableScheduledFuture<V> task) {
369 return task;
370 }
371
372 /**
373 * Modifies or replaces the task used to execute a callable.
374 * This method can be used to override the concrete
375 * class used for managing internal tasks.
376 * The default implementation simply returns the given task.
377 *
378 * @param callable the submitted Callable
379 * @param task the task created to execute the callable
380 * @return a task that can execute the callable
381 * @since 1.6
382 */
383 protected <V> RunnableScheduledFuture<V> decorateTask(
384 Callable<V> callable, RunnableScheduledFuture<V> task) {
385 return task;
386 }
387
388 /**
389 * Creates a new {@code ScheduledThreadPoolExecutor} with the
390 * given core pool size.
391 *
392 * @param corePoolSize the number of threads to keep in the pool, even
393 * if they are idle, unless {@code allowCoreThreadTimeOut} is set
394 * @throws IllegalArgumentException if {@code corePoolSize < 0}
395 */
396 public ScheduledThreadPoolExecutor(int corePoolSize) {
397 super(corePoolSize, Integer.MAX_VALUE, 0, TimeUnit.NANOSECONDS,
398 new DelayedWorkQueue());
399 }
400
401 /**
402 * Creates a new {@code ScheduledThreadPoolExecutor} with the
403 * given initial parameters.
404 *
405 * @param corePoolSize the number of threads to keep in the pool, even
406 * if they are idle, unless {@code allowCoreThreadTimeOut} is set
407 * @param threadFactory the factory to use when the executor
408 * creates a new thread
409 * @throws IllegalArgumentException if {@code corePoolSize < 0}
410 * @throws NullPointerException if {@code threadFactory} is null
411 */
412 public ScheduledThreadPoolExecutor(int corePoolSize,
413 ThreadFactory threadFactory) {
414 super(corePoolSize, Integer.MAX_VALUE, 0, TimeUnit.NANOSECONDS,
415 new DelayedWorkQueue(), threadFactory);
416 }
417
418 /**
419 * Creates a new ScheduledThreadPoolExecutor with the given
420 * initial parameters.
421 *
422 * @param corePoolSize the number of threads to keep in the pool, even
423 * if they are idle, unless {@code allowCoreThreadTimeOut} is set
424 * @param handler the handler to use when execution is blocked
425 * because the thread bounds and queue capacities are reached
426 * @throws IllegalArgumentException if {@code corePoolSize < 0}
427 * @throws NullPointerException if {@code handler} is null
428 */
429 public ScheduledThreadPoolExecutor(int corePoolSize,
430 RejectedExecutionHandler handler) {
431 super(corePoolSize, Integer.MAX_VALUE, 0, TimeUnit.NANOSECONDS,
432 new DelayedWorkQueue(), handler);
433 }
434
435 /**
436 * Creates a new ScheduledThreadPoolExecutor with the given
437 * initial parameters.
438 *
439 * @param corePoolSize the number of threads to keep in the pool, even
440 * if they are idle, unless {@code allowCoreThreadTimeOut} is set
441 * @param threadFactory the factory to use when the executor
442 * creates a new thread
443 * @param handler the handler to use when execution is blocked
444 * because the thread bounds and queue capacities are reached
445 * @throws IllegalArgumentException if {@code corePoolSize < 0}
446 * @throws NullPointerException if {@code threadFactory} or
447 * {@code handler} is null
448 */
449 public ScheduledThreadPoolExecutor(int corePoolSize,
450 ThreadFactory threadFactory,
451 RejectedExecutionHandler handler) {
452 super(corePoolSize, Integer.MAX_VALUE, 0, TimeUnit.NANOSECONDS,
453 new DelayedWorkQueue(), threadFactory, handler);
454 }
455
456 /**
457 * @throws RejectedExecutionException {@inheritDoc}
458 * @throws NullPointerException {@inheritDoc}
459 */
460 public ScheduledFuture<?> schedule(Runnable command,
461 long delay,
462 TimeUnit unit) {
463 if (command == null || unit == null)
464 throw new NullPointerException();
465 if (delay < 0) delay = 0;
466 long triggerTime = now() + unit.toNanos(delay);
467 RunnableScheduledFuture<?> t = decorateTask(command,
468 new ScheduledFutureTask<Void>(command, null, triggerTime));
469 delayedExecute(t);
470 return t;
471 }
472
473 /**
474 * @throws RejectedExecutionException {@inheritDoc}
475 * @throws NullPointerException {@inheritDoc}
476 */
477 public <V> ScheduledFuture<V> schedule(Callable<V> callable,
478 long delay,
479 TimeUnit unit) {
480 if (callable == null || unit == null)
481 throw new NullPointerException();
482 if (delay < 0) delay = 0;
483 long triggerTime = now() + unit.toNanos(delay);
484 RunnableScheduledFuture<V> t = decorateTask(callable,
485 new ScheduledFutureTask<V>(callable, triggerTime));
486 delayedExecute(t);
487 return t;
488 }
489
490 /**
491 * @throws RejectedExecutionException {@inheritDoc}
492 * @throws NullPointerException {@inheritDoc}
493 * @throws IllegalArgumentException {@inheritDoc}
494 */
495 public ScheduledFuture<?> scheduleAtFixedRate(Runnable command,
496 long initialDelay,
497 long period,
498 TimeUnit unit) {
499 if (command == null || unit == null)
500 throw new NullPointerException();
501 if (period <= 0)
502 throw new IllegalArgumentException();
503 if (initialDelay < 0) initialDelay = 0;
504 long triggerTime = now() + unit.toNanos(initialDelay);
505 ScheduledFutureTask<Void> sft =
506 new ScheduledFutureTask<Void>(command,
507 null,
508 triggerTime,
509 unit.toNanos(period));
510 RunnableScheduledFuture<Void> t = decorateTask(command, sft);
511 sft.outerTask = t;
512 delayedExecute(t);
513 return t;
514 }
515
516 /**
517 * @throws RejectedExecutionException {@inheritDoc}
518 * @throws NullPointerException {@inheritDoc}
519 * @throws IllegalArgumentException {@inheritDoc}
520 */
521 public ScheduledFuture<?> scheduleWithFixedDelay(Runnable command,
522 long initialDelay,
523 long delay,
524 TimeUnit unit) {
525 if (command == null || unit == null)
526 throw new NullPointerException();
527 if (delay <= 0)
528 throw new IllegalArgumentException();
529 if (initialDelay < 0) initialDelay = 0;
530 long triggerTime = now() + unit.toNanos(initialDelay);
531 ScheduledFutureTask<Void> sft =
532 new ScheduledFutureTask<Void>(command,
533 null,
534 triggerTime,
535 unit.toNanos(-delay));
536 RunnableScheduledFuture<Void> t = decorateTask(command, sft);
537 sft.outerTask = t;
538 delayedExecute(t);
539 return t;
540 }
541
542 /**
543 * Executes {@code command} with zero required delay.
544 * This has effect equivalent to
545 * {@link #schedule(Runnable,long,TimeUnit) schedule(command, 0, anyUnit)}.
546 * Note that inspections of the queue and of the list returned by
547 * {@code shutdownNow} will access the zero-delayed
548 * {@link ScheduledFuture}, not the {@code command} itself.
549 *
550 * <p>A consequence of the use of {@code ScheduledFuture} objects is
551 * that {@link ThreadPoolExecutor#afterExecute afterExecute} is always
552 * called with a null second {@code Throwable} argument, even if the
553 * {@code command} terminated abruptly. Instead, the {@code Throwable}
554 * thrown by such a task can be obtained via {@link Future#get}.
555 *
556 * @throws RejectedExecutionException at discretion of
557 * {@code RejectedExecutionHandler}, if the task
558 * cannot be accepted for execution because the
559 * executor has been shut down
560 * @throws NullPointerException {@inheritDoc}
561 */
562 public void execute(Runnable command) {
563 schedule(command, 0, TimeUnit.NANOSECONDS);
564 }
565
566 // Override AbstractExecutorService methods
567
568 /**
569 * @throws RejectedExecutionException {@inheritDoc}
570 * @throws NullPointerException {@inheritDoc}
571 */
572 public Future<?> submit(Runnable task) {
573 return schedule(task, 0, TimeUnit.NANOSECONDS);
574 }
575
576 /**
577 * @throws RejectedExecutionException {@inheritDoc}
578 * @throws NullPointerException {@inheritDoc}
579 */
580 public <T> Future<T> submit(Runnable task, T result) {
581 return schedule(Executors.callable(task, result),
582 0, TimeUnit.NANOSECONDS);
583 }
584
585 /**
586 * @throws RejectedExecutionException {@inheritDoc}
587 * @throws NullPointerException {@inheritDoc}
588 */
589 public <T> Future<T> submit(Callable<T> task) {
590 return schedule(task, 0, TimeUnit.NANOSECONDS);
591 }
592
593 /**
594 * Sets the policy on whether to continue executing existing
595 * periodic tasks even when this executor has been {@code shutdown}.
596 * In this case, these tasks will only terminate upon
597 * {@code shutdownNow} or after setting the policy to
598 * {@code false} when already shutdown.
599 * This value is by default {@code false}.
600 *
601 * @param value if {@code true}, continue after shutdown, else don't.
602 * @see #getContinueExistingPeriodicTasksAfterShutdownPolicy
603 */
604 public void setContinueExistingPeriodicTasksAfterShutdownPolicy(boolean value) {
605 continueExistingPeriodicTasksAfterShutdown = value;
606 if (!value && isShutdown())
607 onShutdown();
608 }
609
610 /**
611 * Gets the policy on whether to continue executing existing
612 * periodic tasks even when this executor has been {@code shutdown}.
613 * In this case, these tasks will only terminate upon
614 * {@code shutdownNow} or after setting the policy to
615 * {@code false} when already shutdown.
616 * This value is by default {@code false}.
617 *
618 * @return {@code true} if will continue after shutdown
619 * @see #setContinueExistingPeriodicTasksAfterShutdownPolicy
620 */
621 public boolean getContinueExistingPeriodicTasksAfterShutdownPolicy() {
622 return continueExistingPeriodicTasksAfterShutdown;
623 }
624
625 /**
626 * Sets the policy on whether to execute existing delayed
627 * tasks even when this executor has been {@code shutdown}.
628 * In this case, these tasks will only terminate upon
629 * {@code shutdownNow}, or after setting the policy to
630 * {@code false} when already shutdown.
631 * This value is by default {@code true}.
632 *
633 * @param value if {@code true}, execute after shutdown, else don't.
634 * @see #getExecuteExistingDelayedTasksAfterShutdownPolicy
635 */
636 public void setExecuteExistingDelayedTasksAfterShutdownPolicy(boolean value) {
637 executeExistingDelayedTasksAfterShutdown = value;
638 if (!value && isShutdown())
639 onShutdown();
640 }
641
642 /**
643 * Gets the policy on whether to execute existing delayed
644 * tasks even when this executor has been {@code shutdown}.
645 * In this case, these tasks will only terminate upon
646 * {@code shutdownNow}, or after setting the policy to
647 * {@code false} when already shutdown.
648 * This value is by default {@code true}.
649 *
650 * @return {@code true} if will execute after shutdown
651 * @see #setExecuteExistingDelayedTasksAfterShutdownPolicy
652 */
653 public boolean getExecuteExistingDelayedTasksAfterShutdownPolicy() {
654 return executeExistingDelayedTasksAfterShutdown;
655 }
656
657 /**
658 * Initiates an orderly shutdown in which previously submitted
659 * tasks are executed, but no new tasks will be accepted. If the
660 * {@code ExecuteExistingDelayedTasksAfterShutdownPolicy} has
661 * been set {@code false}, existing delayed tasks whose delays
662 * have not yet elapsed are cancelled. And unless the
663 * {@code ContinueExistingPeriodicTasksAfterShutdownPolicy} has
664 * been set {@code true}, future executions of existing periodic
665 * tasks will be cancelled.
666 *
667 * @throws SecurityException {@inheritDoc}
668 */
669 public void shutdown() {
670 super.shutdown();
671 }
672
673 /**
674 * Attempts to stop all actively executing tasks, halts the
675 * processing of waiting tasks, and returns a list of the tasks
676 * that were awaiting execution.
677 *
678 * <p>There are no guarantees beyond best-effort attempts to stop
679 * processing actively executing tasks. This implementation
680 * cancels tasks via {@link Thread#interrupt}, so any task that
681 * fails to respond to interrupts may never terminate.
682 *
683 * @return list of tasks that never commenced execution.
684 * Each element of this list is a {@link ScheduledFuture},
685 * including those tasks submitted using {@code execute},
686 * which are for scheduling purposes used as the basis of a
687 * zero-delay {@code ScheduledFuture}.
688 * @throws SecurityException {@inheritDoc}
689 */
690 public List<Runnable> shutdownNow() {
691 return super.shutdownNow();
692 }
693
694 /**
695 * Returns the task queue used by this executor. Each element of
696 * this queue is a {@link ScheduledFuture}, including those
697 * tasks submitted using {@code execute} which are for scheduling
698 * purposes used as the basis of a zero-delay
699 * {@code ScheduledFuture}. Iteration over this queue is
700 * <em>not</em> guaranteed to traverse tasks in the order in
701 * which they will execute.
702 *
703 * @return the task queue
704 */
705 public BlockingQueue<Runnable> getQueue() {
706 return super.getQueue();
707 }
708
709 /**
710 * An annoying wrapper class to convince javac to use a
711 * DelayQueue<RunnableScheduledFuture> as a BlockingQueue<Runnable>
712 */
713 private static class DelayedWorkQueue
714 extends AbstractCollection<Runnable>
715 implements BlockingQueue<Runnable> {
716
717 private final DelayQueue<RunnableScheduledFuture> dq = new DelayQueue<RunnableScheduledFuture>();
718 public Runnable poll() { return dq.poll(); }
719 public Runnable peek() { return dq.peek(); }
720 public Runnable take() throws InterruptedException { return dq.take(); }
721 public Runnable poll(long timeout, TimeUnit unit) throws InterruptedException {
722 return dq.poll(timeout, unit);
723 }
724
725 public boolean add(Runnable x) {
726 return dq.add((RunnableScheduledFuture)x);
727 }
728 public boolean offer(Runnable x) {
729 return dq.offer((RunnableScheduledFuture)x);
730 }
731 public void put(Runnable x) {
732 dq.put((RunnableScheduledFuture)x);
733 }
734 public boolean offer(Runnable x, long timeout, TimeUnit unit) {
735 return dq.offer((RunnableScheduledFuture)x, timeout, unit);
736 }
737
738 public Runnable remove() { return dq.remove(); }
739 public Runnable element() { return dq.element(); }
740 public void clear() { dq.clear(); }
741 public int drainTo(Collection<? super Runnable> c) { return dq.drainTo(c); }
742 public int drainTo(Collection<? super Runnable> c, int maxElements) {
743 return dq.drainTo(c, maxElements);
744 }
745
746 public int remainingCapacity() { return dq.remainingCapacity(); }
747 public boolean remove(Object x) { return dq.remove(x); }
748 public boolean contains(Object x) { return dq.contains(x); }
749 public int size() { return dq.size(); }
750 public boolean isEmpty() { return dq.isEmpty(); }
751 public Object[] toArray() { return dq.toArray(); }
752 public <T> T[] toArray(T[] array) { return dq.toArray(array); }
753 public Iterator<Runnable> iterator() {
754 return new Iterator<Runnable>() {
755 private Iterator<RunnableScheduledFuture> it = dq.iterator();
756 public boolean hasNext() { return it.hasNext(); }
757 public Runnable next() { return it.next(); }
758 public void remove() { it.remove(); }
759 };
760 }
761 }
762}