001 /*
002 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
003 *
004 * This code is free software; you can redistribute it and/or modify it
005 * under the terms of the GNU General Public License version 2 only, as
006 * published by the Free Software Foundation. Sun designates this
007 * particular file as subject to the "Classpath" exception as provided
008 * by Sun in the LICENSE file that accompanied this code.
009 *
010 * This code is distributed in the hope that it will be useful, but WITHOUT
011 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
012 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
013 * version 2 for more details (a copy is included in the LICENSE file that
014 * accompanied this code).
015 *
016 * You should have received a copy of the GNU General Public License version
017 * 2 along with this work; if not, write to the Free Software Foundation,
018 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
019 *
020 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
021 * CA 95054 USA or visit www.sun.com if you need additional information or
022 * have any questions.
023 */
024
025 /*
026 * This file is available under and governed by the GNU General Public
027 * License version 2 only, as published by the Free Software Foundation.
028 * However, the following notice accompanied the original version of this
029 * file:
030 *
031 * Written by Doug Lea with assistance from members of JCP JSR-166
032 * Expert Group and released to the public domain, as explained at
033 * http://creativecommons.org/licenses/publicdomain
034 */
035
036 package java.util.concurrent;
037
038 import java.util.concurrent.atomic.*;
039 import java.util.*;
040
041 /**
042 * A {@link ThreadPoolExecutor} that can additionally schedule
043 * commands to run after a given delay, or to execute
044 * periodically. This class is preferable to {@link java.util.Timer}
045 * when multiple worker threads are needed, or when the additional
046 * flexibility or capabilities of {@link ThreadPoolExecutor} (which
047 * this class extends) are required.
048 *
049 * <p> Delayed tasks execute no sooner than they are enabled, but
050 * without any real-time guarantees about when, after they are
051 * enabled, they will commence. Tasks scheduled for exactly the same
052 * execution time are enabled in first-in-first-out (FIFO) order of
053 * submission.
054 *
055 * <p>While this class inherits from {@link ThreadPoolExecutor}, a few
056 * of the inherited tuning methods are not useful for it. In
057 * particular, because it acts as a fixed-sized pool using
058 * {@code corePoolSize} threads and an unbounded queue, adjustments
059 * to {@code maximumPoolSize} have no useful effect. Additionally, it
060 * is almost never a good idea to set {@code corePoolSize} to zero or
061 * use {@code allowCoreThreadTimeOut} because this may leave the pool
062 * without threads to handle tasks once they become eligible to run.
063 *
064 * <p><b>Extension notes:</b> This class overrides the
065 * {@link ThreadPoolExecutor#execute execute} and
066 * {@link AbstractExecutorService#submit(Runnable) submit}
067 * methods to generate internal {@link ScheduledFuture} objects to
068 * control per-task delays and scheduling. To preserve
069 * functionality, any further overrides of these methods in
070 * subclasses must invoke superclass versions, which effectively
071 * disables additional task customization. However, this class
072 * provides alternative protected extension method
073 * {@code decorateTask} (one version each for {@code Runnable} and
074 * {@code Callable}) that can be used to customize the concrete task
075 * types used to execute commands entered via {@code execute},
076 * {@code submit}, {@code schedule}, {@code scheduleAtFixedRate},
077 * and {@code scheduleWithFixedDelay}. By default, a
078 * {@code ScheduledThreadPoolExecutor} uses a task type extending
079 * {@link FutureTask}. However, this may be modified or replaced using
080 * subclasses of the form:
081 *
082 * <pre> {@code
083 * public class CustomScheduledExecutor extends ScheduledThreadPoolExecutor {
084 *
085 * static class CustomTask<V> implements RunnableScheduledFuture<V> { ... }
086 *
087 * protected <V> RunnableScheduledFuture<V> decorateTask(
088 * Runnable r, RunnableScheduledFuture<V> task) {
089 * return new CustomTask<V>(r, task);
090 * }
091 *
092 * protected <V> RunnableScheduledFuture<V> decorateTask(
093 * Callable<V> c, RunnableScheduledFuture<V> task) {
094 * return new CustomTask<V>(c, task);
095 * }
096 * // ... add constructors, etc.
097 * }}</pre>
098 *
099 * @since 1.5
100 * @author Doug Lea
101 */
102 public class ScheduledThreadPoolExecutor 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> extends FutureTask<V>
166 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) - other
234 .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 ? continueExistingPeriodicTasksAfterShutdown
282 : executeExistingDelayedTasksAfterShutdown);
283 }
284
285 /**
286 * Main execution method for delayed or periodic tasks. If pool
287 * is shut down, rejects the task. Otherwise adds task to queue
288 * and starts a thread, if necessary, to run it. (We cannot
289 * prestart the thread to run the task because the task (probably)
290 * shouldn't be run yet,) If the pool is shut down while the task
291 * is being added, cancel and remove it if required by state and
292 * run-after-shutdown parameters.
293 *
294 * @param task the task
295 */
296 private void delayedExecute(RunnableScheduledFuture<?> task) {
297 if (isShutdown())
298 reject(task);
299 else {
300 super .getQueue().add(task);
301 if (isShutdown()
302 && !canRunInCurrentRunState(task.isPeriodic())
303 && remove(task))
304 task.cancel(false);
305 else
306 prestartCoreThread();
307 }
308 }
309
310 /**
311 * Requeues a periodic task unless current run state precludes it.
312 * Same idea as delayedExecute except drops task rather than rejecting.
313 *
314 * @param task the task
315 */
316 void reExecutePeriodic(RunnableScheduledFuture<?> task) {
317 if (canRunInCurrentRunState(true)) {
318 super .getQueue().add(task);
319 if (!canRunInCurrentRunState(true) && remove(task))
320 task.cancel(false);
321 else
322 prestartCoreThread();
323 }
324 }
325
326 /**
327 * Cancels and clears the queue of all tasks that should not be run
328 * due to shutdown policy. Invoked within super.shutdown.
329 */
330 @Override
331 void onShutdown() {
332 BlockingQueue<Runnable> q = super .getQueue();
333 boolean keepDelayed = getExecuteExistingDelayedTasksAfterShutdownPolicy();
334 boolean keepPeriodic = getContinueExistingPeriodicTasksAfterShutdownPolicy();
335 if (!keepDelayed && !keepPeriodic)
336 q.clear();
337 else {
338 // Traverse snapshot to avoid iterator exceptions
339 for (Object e : q.toArray()) {
340 if (e instanceof RunnableScheduledFuture) {
341 RunnableScheduledFuture<?> t = (RunnableScheduledFuture<?>) e;
342 if ((t.isPeriodic() ? !keepPeriodic : !keepDelayed)
343 || t.isCancelled()) { // also remove if already cancelled
344 if (q.remove(t))
345 t.cancel(false);
346 }
347 }
348 }
349 }
350 tryTerminate();
351 }
352
353 /**
354 * Modifies or replaces the task used to execute a runnable.
355 * This method can be used to override the concrete
356 * class used for managing internal tasks.
357 * The default implementation simply returns the given task.
358 *
359 * @param runnable the submitted Runnable
360 * @param task the task created to execute the runnable
361 * @return a task that can execute the runnable
362 * @since 1.6
363 */
364 protected <V> RunnableScheduledFuture<V> decorateTask(
365 Runnable runnable, RunnableScheduledFuture<V> task) {
366 return task;
367 }
368
369 /**
370 * Modifies or replaces the task used to execute a callable.
371 * This method can be used to override the concrete
372 * class used for managing internal tasks.
373 * The default implementation simply returns the given task.
374 *
375 * @param callable the submitted Callable
376 * @param task the task created to execute the callable
377 * @return a task that can execute the callable
378 * @since 1.6
379 */
380 protected <V> RunnableScheduledFuture<V> decorateTask(
381 Callable<V> callable, RunnableScheduledFuture<V> task) {
382 return task;
383 }
384
385 /**
386 * Creates a new {@code ScheduledThreadPoolExecutor} with the
387 * given core pool size.
388 *
389 * @param corePoolSize the number of threads to keep in the pool, even
390 * if they are idle, unless {@code allowCoreThreadTimeOut} is set
391 * @throws IllegalArgumentException if {@code corePoolSize < 0}
392 */
393 public ScheduledThreadPoolExecutor(int corePoolSize) {
394 super (corePoolSize, Integer.MAX_VALUE, 0, TimeUnit.NANOSECONDS,
395 new DelayedWorkQueue());
396 }
397
398 /**
399 * Creates a new {@code ScheduledThreadPoolExecutor} with the
400 * given initial parameters.
401 *
402 * @param corePoolSize the number of threads to keep in the pool, even
403 * if they are idle, unless {@code allowCoreThreadTimeOut} is set
404 * @param threadFactory the factory to use when the executor
405 * creates a new thread
406 * @throws IllegalArgumentException if {@code corePoolSize < 0}
407 * @throws NullPointerException if {@code threadFactory} is null
408 */
409 public ScheduledThreadPoolExecutor(int corePoolSize,
410 ThreadFactory threadFactory) {
411 super (corePoolSize, Integer.MAX_VALUE, 0, TimeUnit.NANOSECONDS,
412 new DelayedWorkQueue(), threadFactory);
413 }
414
415 /**
416 * Creates a new ScheduledThreadPoolExecutor with the given
417 * initial parameters.
418 *
419 * @param corePoolSize the number of threads to keep in the pool, even
420 * if they are idle, unless {@code allowCoreThreadTimeOut} is set
421 * @param handler the handler to use when execution is blocked
422 * because the thread bounds and queue capacities are reached
423 * @throws IllegalArgumentException if {@code corePoolSize < 0}
424 * @throws NullPointerException if {@code handler} is null
425 */
426 public ScheduledThreadPoolExecutor(int corePoolSize,
427 RejectedExecutionHandler handler) {
428 super (corePoolSize, Integer.MAX_VALUE, 0, TimeUnit.NANOSECONDS,
429 new DelayedWorkQueue(), handler);
430 }
431
432 /**
433 * Creates a new ScheduledThreadPoolExecutor with the given
434 * initial parameters.
435 *
436 * @param corePoolSize the number of threads to keep in the pool, even
437 * if they are idle, unless {@code allowCoreThreadTimeOut} is set
438 * @param threadFactory the factory to use when the executor
439 * creates a new thread
440 * @param handler the handler to use when execution is blocked
441 * because the thread bounds and queue capacities are reached
442 * @throws IllegalArgumentException if {@code corePoolSize < 0}
443 * @throws NullPointerException if {@code threadFactory} or
444 * {@code handler} is null
445 */
446 public ScheduledThreadPoolExecutor(int corePoolSize,
447 ThreadFactory threadFactory,
448 RejectedExecutionHandler handler) {
449 super (corePoolSize, Integer.MAX_VALUE, 0, TimeUnit.NANOSECONDS,
450 new DelayedWorkQueue(), threadFactory, handler);
451 }
452
453 /**
454 * @throws RejectedExecutionException {@inheritDoc}
455 * @throws NullPointerException {@inheritDoc}
456 */
457 public ScheduledFuture<?> schedule(Runnable command, long delay,
458 TimeUnit unit) {
459 if (command == null || unit == null)
460 throw new NullPointerException();
461 if (delay < 0)
462 delay = 0;
463 long triggerTime = now() + unit.toNanos(delay);
464 RunnableScheduledFuture<?> t = decorateTask(command,
465 new ScheduledFutureTask<Void>(command, null,
466 triggerTime));
467 delayedExecute(t);
468 return t;
469 }
470
471 /**
472 * @throws RejectedExecutionException {@inheritDoc}
473 * @throws NullPointerException {@inheritDoc}
474 */
475 public <V> ScheduledFuture<V> schedule(Callable<V> callable,
476 long delay, TimeUnit unit) {
477 if (callable == null || unit == null)
478 throw new NullPointerException();
479 if (delay < 0)
480 delay = 0;
481 long triggerTime = now() + unit.toNanos(delay);
482 RunnableScheduledFuture<V> t = decorateTask(callable,
483 new ScheduledFutureTask<V>(callable, triggerTime));
484 delayedExecute(t);
485 return t;
486 }
487
488 /**
489 * @throws RejectedExecutionException {@inheritDoc}
490 * @throws NullPointerException {@inheritDoc}
491 * @throws IllegalArgumentException {@inheritDoc}
492 */
493 public ScheduledFuture<?> scheduleAtFixedRate(Runnable command,
494 long initialDelay, long period, TimeUnit unit) {
495 if (command == null || unit == null)
496 throw new NullPointerException();
497 if (period <= 0)
498 throw new IllegalArgumentException();
499 if (initialDelay < 0)
500 initialDelay = 0;
501 long triggerTime = now() + unit.toNanos(initialDelay);
502 ScheduledFutureTask<Void> sft = new ScheduledFutureTask<Void>(
503 command, null, triggerTime, unit.toNanos(period));
504 RunnableScheduledFuture<Void> t = decorateTask(command, sft);
505 sft.outerTask = t;
506 delayedExecute(t);
507 return t;
508 }
509
510 /**
511 * @throws RejectedExecutionException {@inheritDoc}
512 * @throws NullPointerException {@inheritDoc}
513 * @throws IllegalArgumentException {@inheritDoc}
514 */
515 public ScheduledFuture<?> scheduleWithFixedDelay(Runnable command,
516 long initialDelay, long delay, TimeUnit unit) {
517 if (command == null || unit == null)
518 throw new NullPointerException();
519 if (delay <= 0)
520 throw new IllegalArgumentException();
521 if (initialDelay < 0)
522 initialDelay = 0;
523 long triggerTime = now() + unit.toNanos(initialDelay);
524 ScheduledFutureTask<Void> sft = new ScheduledFutureTask<Void>(
525 command, null, triggerTime, unit.toNanos(-delay));
526 RunnableScheduledFuture<Void> t = decorateTask(command, sft);
527 sft.outerTask = t;
528 delayedExecute(t);
529 return t;
530 }
531
532 /**
533 * Executes {@code command} with zero required delay.
534 * This has effect equivalent to
535 * {@link #schedule(Runnable,long,TimeUnit) schedule(command, 0, anyUnit)}.
536 * Note that inspections of the queue and of the list returned by
537 * {@code shutdownNow} will access the zero-delayed
538 * {@link ScheduledFuture}, not the {@code command} itself.
539 *
540 * <p>A consequence of the use of {@code ScheduledFuture} objects is
541 * that {@link ThreadPoolExecutor#afterExecute afterExecute} is always
542 * called with a null second {@code Throwable} argument, even if the
543 * {@code command} terminated abruptly. Instead, the {@code Throwable}
544 * thrown by such a task can be obtained via {@link Future#get}.
545 *
546 * @throws RejectedExecutionException at discretion of
547 * {@code RejectedExecutionHandler}, if the task
548 * cannot be accepted for execution because the
549 * executor has been shut down
550 * @throws NullPointerException {@inheritDoc}
551 */
552 public void execute(Runnable command) {
553 schedule(command, 0, TimeUnit.NANOSECONDS);
554 }
555
556 // Override AbstractExecutorService methods
557
558 /**
559 * @throws RejectedExecutionException {@inheritDoc}
560 * @throws NullPointerException {@inheritDoc}
561 */
562 public Future<?> submit(Runnable task) {
563 return schedule(task, 0, TimeUnit.NANOSECONDS);
564 }
565
566 /**
567 * @throws RejectedExecutionException {@inheritDoc}
568 * @throws NullPointerException {@inheritDoc}
569 */
570 public <T> Future<T> submit(Runnable task, T result) {
571 return schedule(Executors.callable(task, result), 0,
572 TimeUnit.NANOSECONDS);
573 }
574
575 /**
576 * @throws RejectedExecutionException {@inheritDoc}
577 * @throws NullPointerException {@inheritDoc}
578 */
579 public <T> Future<T> submit(Callable<T> task) {
580 return schedule(task, 0, TimeUnit.NANOSECONDS);
581 }
582
583 /**
584 * Sets the policy on whether to continue executing existing
585 * periodic tasks even when this executor has been {@code shutdown}.
586 * In this case, these tasks will only terminate upon
587 * {@code shutdownNow} or after setting the policy to
588 * {@code false} when already shutdown.
589 * This value is by default {@code false}.
590 *
591 * @param value if {@code true}, continue after shutdown, else don't.
592 * @see #getContinueExistingPeriodicTasksAfterShutdownPolicy
593 */
594 public void setContinueExistingPeriodicTasksAfterShutdownPolicy(
595 boolean value) {
596 continueExistingPeriodicTasksAfterShutdown = value;
597 if (!value && isShutdown())
598 onShutdown();
599 }
600
601 /**
602 * Gets the policy on whether to continue executing existing
603 * periodic tasks even when this executor has been {@code shutdown}.
604 * In this case, these tasks will only terminate upon
605 * {@code shutdownNow} or after setting the policy to
606 * {@code false} when already shutdown.
607 * This value is by default {@code false}.
608 *
609 * @return {@code true} if will continue after shutdown
610 * @see #setContinueExistingPeriodicTasksAfterShutdownPolicy
611 */
612 public boolean getContinueExistingPeriodicTasksAfterShutdownPolicy() {
613 return continueExistingPeriodicTasksAfterShutdown;
614 }
615
616 /**
617 * Sets the policy on whether to execute existing delayed
618 * tasks even when this executor has been {@code shutdown}.
619 * In this case, these tasks will only terminate upon
620 * {@code shutdownNow}, or after setting the policy to
621 * {@code false} when already shutdown.
622 * This value is by default {@code true}.
623 *
624 * @param value if {@code true}, execute after shutdown, else don't.
625 * @see #getExecuteExistingDelayedTasksAfterShutdownPolicy
626 */
627 public void setExecuteExistingDelayedTasksAfterShutdownPolicy(
628 boolean value) {
629 executeExistingDelayedTasksAfterShutdown = value;
630 if (!value && isShutdown())
631 onShutdown();
632 }
633
634 /**
635 * Gets the policy on whether to execute existing delayed
636 * tasks even when this executor has been {@code shutdown}.
637 * In this case, these tasks will only terminate upon
638 * {@code shutdownNow}, or after setting the policy to
639 * {@code false} when already shutdown.
640 * This value is by default {@code true}.
641 *
642 * @return {@code true} if will execute after shutdown
643 * @see #setExecuteExistingDelayedTasksAfterShutdownPolicy
644 */
645 public boolean getExecuteExistingDelayedTasksAfterShutdownPolicy() {
646 return executeExistingDelayedTasksAfterShutdown;
647 }
648
649 /**
650 * Initiates an orderly shutdown in which previously submitted
651 * tasks are executed, but no new tasks will be accepted. If the
652 * {@code ExecuteExistingDelayedTasksAfterShutdownPolicy} has
653 * been set {@code false}, existing delayed tasks whose delays
654 * have not yet elapsed are cancelled. And unless the
655 * {@code ContinueExistingPeriodicTasksAfterShutdownPolicy} has
656 * been set {@code true}, future executions of existing periodic
657 * tasks will be cancelled.
658 *
659 * @throws SecurityException {@inheritDoc}
660 */
661 public void shutdown() {
662 super .shutdown();
663 }
664
665 /**
666 * Attempts to stop all actively executing tasks, halts the
667 * processing of waiting tasks, and returns a list of the tasks
668 * that were awaiting execution.
669 *
670 * <p>There are no guarantees beyond best-effort attempts to stop
671 * processing actively executing tasks. This implementation
672 * cancels tasks via {@link Thread#interrupt}, so any task that
673 * fails to respond to interrupts may never terminate.
674 *
675 * @return list of tasks that never commenced execution.
676 * Each element of this list is a {@link ScheduledFuture},
677 * including those tasks submitted using {@code execute},
678 * which are for scheduling purposes used as the basis of a
679 * zero-delay {@code ScheduledFuture}.
680 * @throws SecurityException {@inheritDoc}
681 */
682 public List<Runnable> shutdownNow() {
683 return super .shutdownNow();
684 }
685
686 /**
687 * Returns the task queue used by this executor. Each element of
688 * this queue is a {@link ScheduledFuture}, including those
689 * tasks submitted using {@code execute} which are for scheduling
690 * purposes used as the basis of a zero-delay
691 * {@code ScheduledFuture}. Iteration over this queue is
692 * <em>not</em> guaranteed to traverse tasks in the order in
693 * which they will execute.
694 *
695 * @return the task queue
696 */
697 public BlockingQueue<Runnable> getQueue() {
698 return super .getQueue();
699 }
700
701 /**
702 * An annoying wrapper class to convince javac to use a
703 * DelayQueue<RunnableScheduledFuture> as a BlockingQueue<Runnable>
704 */
705 private static class DelayedWorkQueue extends
706 AbstractCollection<Runnable> implements
707 BlockingQueue<Runnable> {
708
709 private final DelayQueue<RunnableScheduledFuture> dq = new DelayQueue<RunnableScheduledFuture>();
710
711 public Runnable poll() {
712 return dq.poll();
713 }
714
715 public Runnable peek() {
716 return dq.peek();
717 }
718
719 public Runnable take() throws InterruptedException {
720 return dq.take();
721 }
722
723 public Runnable poll(long timeout, TimeUnit unit)
724 throws InterruptedException {
725 return dq.poll(timeout, unit);
726 }
727
728 public boolean add(Runnable x) {
729 return dq.add((RunnableScheduledFuture) x);
730 }
731
732 public boolean offer(Runnable x) {
733 return dq.offer((RunnableScheduledFuture) x);
734 }
735
736 public void put(Runnable x) {
737 dq.put((RunnableScheduledFuture) x);
738 }
739
740 public boolean offer(Runnable x, long timeout, TimeUnit unit) {
741 return dq.offer((RunnableScheduledFuture) x, timeout, unit);
742 }
743
744 public Runnable remove() {
745 return dq.remove();
746 }
747
748 public Runnable element() {
749 return dq.element();
750 }
751
752 public void clear() {
753 dq.clear();
754 }
755
756 public int drainTo(Collection<? super Runnable> c) {
757 return dq.drainTo(c);
758 }
759
760 public int drainTo(Collection<? super Runnable> c,
761 int maxElements) {
762 return dq.drainTo(c, maxElements);
763 }
764
765 public int remainingCapacity() {
766 return dq.remainingCapacity();
767 }
768
769 public boolean remove(Object x) {
770 return dq.remove(x);
771 }
772
773 public boolean contains(Object x) {
774 return dq.contains(x);
775 }
776
777 public int size() {
778 return dq.size();
779 }
780
781 public boolean isEmpty() {
782 return dq.isEmpty();
783 }
784
785 public Object[] toArray() {
786 return dq.toArray();
787 }
788
789 public <T> T[] toArray(T[] array) {
790 return dq.toArray(array);
791 }
792
793 public Iterator<Runnable> iterator() {
794 return new Iterator<Runnable>() {
795 private Iterator<RunnableScheduledFuture> it = dq
796 .iterator();
797
798 public boolean hasNext() {
799 return it.hasNext();
800 }
801
802 public Runnable next() {
803 return it.next();
804 }
805
806 public void remove() {
807 it.remove();
808 }
809 };
810 }
811 }
812 }
|