ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/main/java/util/concurrent/ScheduledThreadPoolExecutor.java
Revision: 1.38
Committed: Sun Sep 3 06:04:35 2006 UTC (17 years, 9 months ago) by jsr166
Branch: MAIN
Changes since 1.37: +3 -3 lines
Log Message:
minor fixes

File Contents

# User Rev Content
1 dl 1.1 /*
2     * Written by Doug Lea with assistance from members of JCP JSR-166
3 dl 1.11 * Expert Group and released to the public domain, as explained at
4     * http://creativecommons.org/licenses/publicdomain
5 dl 1.1 */
6    
7     package java.util.concurrent;
8     import java.util.concurrent.atomic.*;
9     import java.util.*;
10    
11     /**
12 dl 1.7 * 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 dl 1.1 *
19     * <p> Delayed tasks execute no sooner than they are enabled, but
20 dl 1.18 * 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 dl 1.1 *
25     * <p>While this class inherits from {@link ThreadPoolExecutor}, a few
26 dl 1.8 * 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 dl 1.37 * 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 dl 1.1 *
34 dl 1.32 * <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 dl 1.23 * <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 dl 1.32 * 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 jsr166 1.33 * <pre>
51 dl 1.23 * public class CustomScheduledExecutor extends ScheduledThreadPoolExecutor {
52     *
53 jsr166 1.29 * static class CustomTask&lt;V&gt; implements RunnableScheduledFuture&lt;V&gt; { ... }
54 dl 1.23 *
55 jsr166 1.29 * 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 dl 1.23 *
60 jsr166 1.29 * 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 dl 1.23 * }
66     * </pre>
67 dl 1.1 * @since 1.5
68     * @author Doug Lea
69     */
70 jsr166 1.21 public class ScheduledThreadPoolExecutor
71     extends ThreadPoolExecutor
72 tim 1.3 implements ScheduledExecutorService {
73 dl 1.1
74 dl 1.37 /*
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 dl 1.1 /**
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 dl 1.14
127     /** Base of nanosecond timings, to avoid wrapping */
128     private static final long NANO_ORIGIN = System.nanoTime();
129    
130     /**
131 dl 1.18 * Returns nanosecond time offset by origin
132 dl 1.14 */
133 dl 1.17 final long now() {
134 peierls 1.22 return System.nanoTime() - NANO_ORIGIN;
135 dl 1.14 }
136    
137 jsr166 1.21 private class ScheduledFutureTask<V>
138 peierls 1.22 extends FutureTask<V> implements RunnableScheduledFuture<V> {
139 jsr166 1.21
140 dl 1.1 /** 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 dl 1.16 /**
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 dl 1.1 private final long period;
151    
152     /**
153 jsr166 1.30 * Creates a one-shot action with given nanoTime-based trigger time.
154 dl 1.1 */
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 jsr166 1.30 * Creates a periodic action with given nano time and period.
164 dl 1.1 */
165 jsr166 1.30 ScheduledFutureTask(Runnable r, V result, long ns, long period) {
166 dl 1.1 super(r, result);
167     this.time = ns;
168     this.period = period;
169     this.sequenceNumber = sequencer.getAndIncrement();
170     }
171    
172     /**
173 jsr166 1.30 * Creates a one-shot action with given nanoTime-based trigger.
174 dl 1.1 */
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 dl 1.14 long d = unit.convert(time - now(), TimeUnit.NANOSECONDS);
184 dl 1.1 return d;
185     }
186    
187 dl 1.20 public int compareTo(Delayed other) {
188 dl 1.1 if (other == this) // compare zero ONLY if same object
189     return 0;
190 dl 1.34 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 jsr166 1.38 return (d == 0) ? 0 : ((d < 0) ? -1 : 1);
205 dl 1.1 }
206    
207     /**
208 dl 1.18 * Returns true if this is a periodic (not a one-shot) action.
209 jsr166 1.30 *
210 dl 1.1 * @return true if periodic
211     */
212 dl 1.23 public boolean isPeriodic() {
213 dl 1.16 return period != 0;
214 dl 1.1 }
215    
216     /**
217 dl 1.37 * Sets the next time to run for a periodic task
218 dl 1.13 */
219 dl 1.37 private void setNextRunTime() {
220     long p = period;
221     if (p > 0)
222     time += p;
223     else
224     time = now() - p;
225 dl 1.13 }
226    
227     /**
228 dl 1.5 * Overrides FutureTask version so as to reset/requeue if periodic.
229 jsr166 1.21 */
230 dl 1.1 public void run() {
231 dl 1.37 boolean periodic = isPeriodic();
232     if (!canRunInCurrentRunState(periodic))
233     cancel(false);
234     else if (!periodic)
235 dl 1.5 ScheduledFutureTask.super.run();
236 dl 1.37 else if (ScheduledFutureTask.super.runAndReset()) {
237     setNextRunTime();
238     reExecutePeriodic(this);
239     }
240 dl 1.1 }
241     }
242    
243     /**
244 dl 1.37 * 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 jsr166 1.38 return isRunningOrShutdown(periodic ?
250 dl 1.37 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 dl 1.13 prestartCoreThread();
274 dl 1.37 }
275     }
276 jsr166 1.21
277 dl 1.37 /**
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 dl 1.13 }
291 dl 1.1
292 dl 1.13 /**
293 jsr166 1.21 * Cancels and clears the queue of all tasks that should not be run
294 dl 1.37 * due to shutdown policy. Invoked within super.shutdown.
295 dl 1.13 */
296 dl 1.37 @Override void onShutdown() {
297     BlockingQueue<Runnable> q = super.getQueue();
298     boolean keepDelayed =
299     getExecuteExistingDelayedTasksAfterShutdownPolicy();
300     boolean keepPeriodic =
301     getContinueExistingPeriodicTasksAfterShutdownPolicy();
302 jsr166 1.21 if (!keepDelayed && !keepPeriodic)
303 dl 1.37 q.clear();
304     else {
305     // Traverse snapshot to avoid iterator exceptions
306     Object[] entries = q.toArray();
307 dl 1.13 for (int i = 0; i < entries.length; ++i) {
308     Object e = entries[i];
309 dl 1.23 if (e instanceof RunnableScheduledFuture) {
310 dl 1.37 RunnableScheduledFuture<?> t =
311     (RunnableScheduledFuture<?>)e;
312 jsr166 1.38 if ((t.isPeriodic() ? !keepPeriodic : !keepDelayed) ||
313 dl 1.37 t.isCancelled()) { // also remove if already cancelled
314     if (q.remove(t))
315     t.cancel(false);
316     }
317 dl 1.13 }
318     }
319 dl 1.1 }
320     }
321    
322 dl 1.23 /**
323 jsr166 1.30 * Modifies or replaces the task used to execute a runnable.
324 jsr166 1.28 * This method can be used to override the concrete
325 dl 1.23 * class used for managing internal tasks.
326 jsr166 1.30 * The default implementation simply returns the given task.
327 jsr166 1.28 *
328 dl 1.23 * @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 peierls 1.22 protected <V> RunnableScheduledFuture<V> decorateTask(
334 dl 1.23 Runnable runnable, RunnableScheduledFuture<V> task) {
335     return task;
336 peierls 1.22 }
337    
338 dl 1.23 /**
339 jsr166 1.30 * Modifies or replaces the task used to execute a callable.
340 jsr166 1.28 * This method can be used to override the concrete
341 dl 1.23 * class used for managing internal tasks.
342 jsr166 1.30 * The default implementation simply returns the given task.
343 jsr166 1.28 *
344 dl 1.23 * @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 peierls 1.22 protected <V> RunnableScheduledFuture<V> decorateTask(
350 dl 1.23 Callable<V> callable, RunnableScheduledFuture<V> task) {
351     return task;
352 dl 1.19 }
353    
354 dl 1.1 /**
355 dl 1.13 * Creates a new ScheduledThreadPoolExecutor with the given core
356     * pool size.
357 jsr166 1.21 *
358 dl 1.1 * @param corePoolSize the number of threads to keep in the pool,
359 dl 1.37 * even if they are idle, unless allowCoreThreadTimeOut is set
360 dl 1.36 * @throws IllegalArgumentException if <tt>corePoolSize &lt; 0</tt>
361 dl 1.1 */
362     public ScheduledThreadPoolExecutor(int corePoolSize) {
363     super(corePoolSize, Integer.MAX_VALUE, 0, TimeUnit.NANOSECONDS,
364     new DelayedWorkQueue());
365     }
366    
367     /**
368 dl 1.13 * Creates a new ScheduledThreadPoolExecutor with the given
369     * initial parameters.
370 jsr166 1.21 *
371 dl 1.1 * @param corePoolSize the number of threads to keep in the pool,
372 dl 1.37 * even if they are idle, unless allowCoreThreadTimeOut is set
373 dl 1.1 * @param threadFactory the factory to use when the executor
374 jsr166 1.30 * creates a new thread
375 dl 1.36 * @throws IllegalArgumentException if <tt>corePoolSize &lt; 0</tt>
376 dl 1.1 * @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 dl 1.13 * Creates a new ScheduledThreadPoolExecutor with the given
386     * initial parameters.
387 jsr166 1.21 *
388 dl 1.1 * @param corePoolSize the number of threads to keep in the pool,
389 dl 1.37 * even if they are idle, unless allowCoreThreadTimeOut is set
390 dl 1.1 * @param handler the handler to use when execution is blocked
391 jsr166 1.30 * because the thread bounds and queue capacities are reached
392 dl 1.36 * @throws IllegalArgumentException if <tt>corePoolSize &lt; 0</tt>
393 dl 1.1 * @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 dl 1.13 * Creates a new ScheduledThreadPoolExecutor with the given
403     * initial parameters.
404 jsr166 1.21 *
405 dl 1.1 * @param corePoolSize the number of threads to keep in the pool,
406 dl 1.37 * even if they are idle, unless allowCoreThreadTimeOut is set
407 dl 1.1 * @param threadFactory the factory to use when the executor
408 jsr166 1.30 * creates a new thread
409 dl 1.1 * @param handler the handler to use when execution is blocked
410     * because the thread bounds and queue capacities are reached.
411 dl 1.36 * @throws IllegalArgumentException if <tt>corePoolSize &lt; 0</tt>
412 dl 1.1 * @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 dl 1.37 /**
422     * @throws RejectedExecutionException {@inheritDoc}
423     * @throws NullPointerException {@inheritDoc}
424     */
425 jsr166 1.21 public ScheduledFuture<?> schedule(Runnable command,
426     long delay,
427 dl 1.13 TimeUnit unit) {
428 dl 1.9 if (command == null || unit == null)
429 dl 1.1 throw new NullPointerException();
430 dl 1.37 if (delay < 0) delay = 0;
431 dl 1.14 long triggerTime = now() + unit.toNanos(delay);
432 peierls 1.22 RunnableScheduledFuture<?> t = decorateTask(command,
433     new ScheduledFutureTask<Boolean>(command, null, triggerTime));
434 dl 1.1 delayedExecute(t);
435     return t;
436     }
437    
438 dl 1.37 /**
439     * @throws RejectedExecutionException {@inheritDoc}
440     * @throws NullPointerException {@inheritDoc}
441     */
442 jsr166 1.21 public <V> ScheduledFuture<V> schedule(Callable<V> callable,
443     long delay,
444 dl 1.13 TimeUnit unit) {
445 dl 1.9 if (callable == null || unit == null)
446 dl 1.1 throw new NullPointerException();
447 dl 1.16 if (delay < 0) delay = 0;
448 dl 1.14 long triggerTime = now() + unit.toNanos(delay);
449 peierls 1.22 RunnableScheduledFuture<V> t = decorateTask(callable,
450     new ScheduledFutureTask<V>(callable, triggerTime));
451 dl 1.1 delayedExecute(t);
452     return t;
453     }
454    
455 dl 1.37 /**
456     * @throws RejectedExecutionException {@inheritDoc}
457     * @throws NullPointerException {@inheritDoc}
458     * @throws IllegalArgumentException {@inheritDoc}
459     */
460 jsr166 1.21 public ScheduledFuture<?> scheduleAtFixedRate(Runnable command,
461     long initialDelay,
462     long period,
463 dl 1.13 TimeUnit unit) {
464 dl 1.9 if (command == null || unit == null)
465 dl 1.1 throw new NullPointerException();
466     if (period <= 0)
467     throw new IllegalArgumentException();
468 dl 1.16 if (initialDelay < 0) initialDelay = 0;
469 dl 1.14 long triggerTime = now() + unit.toNanos(initialDelay);
470 peierls 1.22 RunnableScheduledFuture<?> t = decorateTask(command,
471 jsr166 1.21 new ScheduledFutureTask<Object>(command,
472 dl 1.13 null,
473     triggerTime,
474 peierls 1.22 unit.toNanos(period)));
475 dl 1.1 delayedExecute(t);
476     return t;
477     }
478 jsr166 1.21
479 dl 1.37 /**
480     * @throws RejectedExecutionException {@inheritDoc}
481     * @throws NullPointerException {@inheritDoc}
482     * @throws IllegalArgumentException {@inheritDoc}
483     */
484 jsr166 1.21 public ScheduledFuture<?> scheduleWithFixedDelay(Runnable command,
485     long initialDelay,
486     long delay,
487 dl 1.13 TimeUnit unit) {
488 dl 1.9 if (command == null || unit == null)
489 dl 1.1 throw new NullPointerException();
490     if (delay <= 0)
491     throw new IllegalArgumentException();
492 dl 1.16 if (initialDelay < 0) initialDelay = 0;
493 dl 1.14 long triggerTime = now() + unit.toNanos(initialDelay);
494 peierls 1.22 RunnableScheduledFuture<?> t = decorateTask(command,
495 jsr166 1.21 new ScheduledFutureTask<Boolean>(command,
496 dl 1.13 null,
497     triggerTime,
498 peierls 1.22 unit.toNanos(-delay)));
499 dl 1.1 delayedExecute(t);
500     return t;
501     }
502 jsr166 1.21
503 dl 1.1 /**
504 jsr166 1.21 * Executes command with zero required delay. This has effect
505 dl 1.1 * 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 dl 1.13 // Override AbstractExecutorService methods
523    
524 dl 1.37 /**
525     * @throws RejectedExecutionException {@inheritDoc}
526     * @throws NullPointerException {@inheritDoc}
527     */
528 dl 1.7 public Future<?> submit(Runnable task) {
529     return schedule(task, 0, TimeUnit.NANOSECONDS);
530     }
531    
532 dl 1.37 /**
533     * @throws RejectedExecutionException {@inheritDoc}
534     * @throws NullPointerException {@inheritDoc}
535     */
536 dl 1.7 public <T> Future<T> submit(Runnable task, T result) {
537 jsr166 1.21 return schedule(Executors.callable(task, result),
538 dl 1.13 0, TimeUnit.NANOSECONDS);
539 dl 1.7 }
540    
541 dl 1.37 /**
542     * @throws RejectedExecutionException {@inheritDoc}
543     * @throws NullPointerException {@inheritDoc}
544     */
545 dl 1.7 public <T> Future<T> submit(Callable<T> task) {
546     return schedule(task, 0, TimeUnit.NANOSECONDS);
547     }
548 dl 1.1
549     /**
550 dl 1.37 * 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 jsr166 1.30 *
557 dl 1.1 * @param value if true, continue after shutdown, else don't.
558 jsr166 1.25 * @see #getContinueExistingPeriodicTasksAfterShutdownPolicy
559 dl 1.1 */
560     public void setContinueExistingPeriodicTasksAfterShutdownPolicy(boolean value) {
561     continueExistingPeriodicTasksAfterShutdown = value;
562 dl 1.37 if (!value && isShutdown()) {
563     onShutdown();
564     tryTerminate();
565     }
566 dl 1.1 }
567    
568     /**
569 jsr166 1.21 * Gets the policy on whether to continue executing existing
570 dl 1.1 * 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 jsr166 1.30 *
576     * @return true if will continue after shutdown
577 dl 1.16 * @see #setContinueExistingPeriodicTasksAfterShutdownPolicy
578 dl 1.1 */
579     public boolean getContinueExistingPeriodicTasksAfterShutdownPolicy() {
580     return continueExistingPeriodicTasksAfterShutdown;
581     }
582    
583     /**
584 jsr166 1.21 * Sets the policy on whether to execute existing delayed
585 dl 1.1 * 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 jsr166 1.30 *
591 dl 1.1 * @param value if true, execute after shutdown, else don't.
592 dl 1.16 * @see #getExecuteExistingDelayedTasksAfterShutdownPolicy
593 dl 1.1 */
594     public void setExecuteExistingDelayedTasksAfterShutdownPolicy(boolean value) {
595     executeExistingDelayedTasksAfterShutdown = value;
596 dl 1.37 if (!value && isShutdown()) {
597     onShutdown();
598     tryTerminate();
599     }
600 dl 1.1 }
601    
602     /**
603 jsr166 1.21 * Gets the policy on whether to execute existing delayed
604 dl 1.1 * 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 jsr166 1.30 *
610     * @return true if will execute after shutdown
611 dl 1.16 * @see #setExecuteExistingDelayedTasksAfterShutdownPolicy
612 dl 1.1 */
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 jsr166 1.30 * processing of waiting tasks, and returns a list of the tasks
634     * that were awaiting execution.
635 jsr166 1.21 *
636 dl 1.1 * <p>There are no guarantees beyond best-effort attempts to stop
637 dl 1.18 * processing actively executing tasks. This implementation
638 jsr166 1.31 * cancels tasks via {@link Thread#interrupt}, so any task that
639     * fails to respond to interrupts may never terminate.
640 dl 1.1 *
641     * @return list of tasks that never commenced execution. Each
642     * element of this list is a {@link ScheduledFuture},
643 dl 1.18 * including those tasks submitted using <tt>execute</tt>, which
644 dl 1.1 * are for scheduling purposes used as the basis of a zero-delay
645     * <tt>ScheduledFuture</tt>.
646 jsr166 1.31 * @throws SecurityException {@inheritDoc}
647 dl 1.1 */
648 tim 1.4 public List<Runnable> shutdownNow() {
649 dl 1.1 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 dl 1.15 * <em>not</em> guaranteed to traverse tasks in the order in
659 dl 1.1 * which they will execute.
660     *
661     * @return the task queue
662     */
663     public BlockingQueue<Runnable> getQueue() {
664     return super.getQueue();
665     }
666    
667 dl 1.13 /**
668 jsr166 1.27 * An annoying wrapper class to convince javac to use a
669     * DelayQueue<RunnableScheduledFuture> as a BlockingQueue<Runnable>
670 jsr166 1.21 */
671     private static class DelayedWorkQueue
672     extends AbstractCollection<Runnable>
673 dl 1.13 implements BlockingQueue<Runnable> {
674 jsr166 1.21
675 dl 1.23 private final DelayQueue<RunnableScheduledFuture> dq = new DelayQueue<RunnableScheduledFuture>();
676 dl 1.13 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 jsr166 1.27 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 jsr166 1.30 public void put(Runnable x) {
690 dl 1.23 dq.put((RunnableScheduledFuture)x);
691 dl 1.13 }
692     public boolean offer(Runnable x, long timeout, TimeUnit unit) {
693 dl 1.23 return dq.offer((RunnableScheduledFuture)x, timeout, unit);
694 dl 1.13 }
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 jsr166 1.21 public int drainTo(Collection<? super Runnable> c, int maxElements) {
701     return dq.drainTo(c, maxElements);
702 dl 1.13 }
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 jsr166 1.21 public Iterator<Runnable> iterator() {
712 dl 1.13 return new Iterator<Runnable>() {
713 dl 1.23 private Iterator<RunnableScheduledFuture> it = dq.iterator();
714 dl 1.13 public boolean hasNext() { return it.hasNext(); }
715     public Runnable next() { return it.next(); }
716 jsr166 1.30 public void remove() { it.remove(); }
717 dl 1.13 };
718     }
719     }
720 dl 1.1 }