ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/main/java/util/concurrent/ScheduledThreadPoolExecutor.java
Revision: 1.37
Committed: Tue Aug 29 23:30:36 2006 UTC (17 years, 9 months ago) by dl
Branch: MAIN
Changes since 1.36: +167 -70 lines
Log Message:
Internal refactoring

File Contents

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