KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > java > util > concurrent > Executors


1 /*
2  * @(#)Executors.java 1.6 04/02/09
3  *
4  * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
5  * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
6  */

7
8 package java.util.concurrent;
9 import java.util.*;
10 import java.util.concurrent.atomic.AtomicInteger JavaDoc;
11 import java.security.AccessControlContext JavaDoc;
12 import java.security.AccessController JavaDoc;
13 import java.security.PrivilegedAction JavaDoc;
14 import java.security.PrivilegedExceptionAction JavaDoc;
15 import java.security.AccessControlException JavaDoc;
16
17 /**
18  * Factory and utility methods for {@link Executor}, {@link
19  * ExecutorService}, {@link ScheduledExecutorService}, {@link
20  * ThreadFactory}, and {@link Callable} classes defined in this
21  * package. This class supports the following kinds of methods:
22  *
23  * <ul>
24  * <li> Methods that create and return an {@link ExecutorService}
25  * set up with commonly useful configuration settings.
26  * <li> Methods that create and return a {@link ScheduledExecutorService}
27  * set up with commonly useful configuration settings.
28  * <li> Methods that create and return a "wrapped" ExecutorService, that
29  * disables reconfiguration by making implementation-specific methods
30  * inaccessible.
31  * <li> Methods that create and return a {@link ThreadFactory}
32  * that sets newly created threads to a known state.
33  * <li> Methods that create and return a {@link Callable}
34  * out of other closure-like forms, so they can be used
35  * in execution methods requiring <tt>Callable</tt>.
36  * </ul>
37  *
38  * @since 1.5
39  * @author Doug Lea
40  */

41 public class Executors {
42
43     /**
44      * Creates a thread pool that reuses a fixed set of threads
45      * operating off a shared unbounded queue. If any thread
46      * terminates due to a failure during execution prior to shutdown,
47      * a new one will take its place if needed to execute subsequent
48      * tasks.
49      *
50      * @param nThreads the number of threads in the pool
51      * @return the newly created thread pool
52      */

53     public static ExecutorService JavaDoc newFixedThreadPool(int nThreads) {
54         return new ThreadPoolExecutor JavaDoc(nThreads, nThreads,
55                                       0L, TimeUnit.MILLISECONDS,
56                                       new LinkedBlockingQueue JavaDoc<Runnable JavaDoc>());
57     }
58
59     /**
60      * Creates a thread pool that reuses a fixed set of threads
61      * operating off a shared unbounded queue, using the provided
62      * ThreadFactory to create new threads when needed.
63      *
64      * @param nThreads the number of threads in the pool
65      * @param threadFactory the factory to use when creating new threads
66      * @return the newly created thread pool
67      */

68     public static ExecutorService JavaDoc newFixedThreadPool(int nThreads, ThreadFactory JavaDoc threadFactory) {
69         return new ThreadPoolExecutor JavaDoc(nThreads, nThreads,
70                                       0L, TimeUnit.MILLISECONDS,
71                                       new LinkedBlockingQueue JavaDoc<Runnable JavaDoc>(),
72                                       threadFactory);
73     }
74
75     /**
76      * Creates an Executor that uses a single worker thread operating
77      * off an unbounded queue. (Note however that if this single
78      * thread terminates due to a failure during execution prior to
79      * shutdown, a new one will take its place if needed to execute
80      * subsequent tasks.) Tasks are guaranteed to execute
81      * sequentially, and no more than one task will be active at any
82      * given time. Unlike the otherwise equivalent
83      * <tt>newFixedThreadPool(1)</tt> the returned executor is
84      * guaranteed not to be reconfigurable to use additional threads.
85      *
86      * @return the newly created single-threaded Executor
87      */

88     public static ExecutorService JavaDoc newSingleThreadExecutor() {
89         return new DelegatedExecutorService
90             (new ThreadPoolExecutor JavaDoc(1, 1,
91                                     0L, TimeUnit.MILLISECONDS,
92                                     new LinkedBlockingQueue JavaDoc<Runnable JavaDoc>()));
93     }
94
95     /**
96      * Creates an Executor that uses a single worker thread operating
97      * off an unbounded queue, and uses the provided ThreadFactory to
98      * create a new thread when needed. Unlike the otherwise
99      * equivalent <tt>newFixedThreadPool(1, threadFactory)</tt> the returned executor
100      * is guaranteed not to be reconfigurable to use additional
101      * threads.
102      *
103      * @param threadFactory the factory to use when creating new
104      * threads
105      *
106      * @return the newly created single-threaded Executor
107      */

108     public static ExecutorService JavaDoc newSingleThreadExecutor(ThreadFactory JavaDoc threadFactory) {
109         return new DelegatedExecutorService
110             (new ThreadPoolExecutor JavaDoc(1, 1,
111                                     0L, TimeUnit.MILLISECONDS,
112                                     new LinkedBlockingQueue JavaDoc<Runnable JavaDoc>(),
113                                     threadFactory));
114     }
115
116     /**
117      * Creates a thread pool that creates new threads as needed, but
118      * will reuse previously constructed threads when they are
119      * available. These pools will typically improve the performance
120      * of programs that execute many short-lived asynchronous tasks.
121      * Calls to <tt>execute</tt> will reuse previously constructed
122      * threads if available. If no existing thread is available, a new
123      * thread will be created and added to the pool. Threads that have
124      * not been used for sixty seconds are terminated and removed from
125      * the cache. Thus, a pool that remains idle for long enough will
126      * not consume any resources. Note that pools with similar
127      * properties but different details (for example, timeout parameters)
128      * may be created using {@link ThreadPoolExecutor} constructors.
129      *
130      * @return the newly created thread pool
131      */

132     public static ExecutorService JavaDoc newCachedThreadPool() {
133         return new ThreadPoolExecutor JavaDoc(0, Integer.MAX_VALUE,
134                                       60L, TimeUnit.SECONDS,
135                                       new SynchronousQueue JavaDoc<Runnable JavaDoc>());
136     }
137
138     /**
139      * Creates a thread pool that creates new threads as needed, but
140      * will reuse previously constructed threads when they are
141      * available, and uses the provided
142      * ThreadFactory to create new threads when needed.
143      * @param threadFactory the factory to use when creating new threads
144      * @return the newly created thread pool
145      */

146     public static ExecutorService JavaDoc newCachedThreadPool(ThreadFactory JavaDoc threadFactory) {
147         return new ThreadPoolExecutor JavaDoc(0, Integer.MAX_VALUE,
148                                       60L, TimeUnit.SECONDS,
149                                       new SynchronousQueue JavaDoc<Runnable JavaDoc>(),
150                                       threadFactory);
151     }
152    
153     /**
154      * Creates a single-threaded executor that can schedule commands
155      * to run after a given delay, or to execute periodically.
156      * (Note however that if this single
157      * thread terminates due to a failure during execution prior to
158      * shutdown, a new one will take its place if needed to execute
159      * subsequent tasks.) Tasks are guaranteed to execute
160      * sequentially, and no more than one task will be active at any
161      * given time. Unlike the otherwise equivalent
162      * <tt>newScheduledThreadPool(1)</tt> the returned executor is
163      * guaranteed not to be reconfigurable to use additional threads.
164      * @return the newly created scheduled executor
165      */

166     public static ScheduledExecutorService JavaDoc newSingleThreadScheduledExecutor() {
167         return new DelegatedScheduledExecutorService
168             (new ScheduledThreadPoolExecutor JavaDoc(1));
169     }
170
171     /**
172      * Creates a single-threaded executor that can schedule commands
173      * to run after a given delay, or to execute periodically. (Note
174      * however that if this single thread terminates due to a failure
175      * during execution prior to shutdown, a new one will take its
176      * place if needed to execute subsequent tasks.) Tasks are
177      * guaranteed to execute sequentially, and no more than one task
178      * will be active at any given time. Unlike the otherwise
179      * equivalent <tt>newScheduledThreadPool(1, threadFactory)</tt>
180      * the returned executor is guaranteed not to be reconfigurable to
181      * use additional threads.
182      * @param threadFactory the factory to use when creating new
183      * threads
184      * @return a newly created scheduled executor
185      */

186     public static ScheduledExecutorService JavaDoc newSingleThreadScheduledExecutor(ThreadFactory JavaDoc threadFactory) {
187         return new DelegatedScheduledExecutorService
188             (new ScheduledThreadPoolExecutor JavaDoc(1, threadFactory));
189     }
190     
191     /**
192      * Creates a thread pool that can schedule commands to run after a
193      * given delay, or to execute periodically.
194      * @param corePoolSize the number of threads to keep in the pool,
195      * even if they are idle.
196      * @return a newly created scheduled thread pool
197      */

198     public static ScheduledExecutorService JavaDoc newScheduledThreadPool(int corePoolSize) {
199         return new ScheduledThreadPoolExecutor JavaDoc(corePoolSize);
200     }
201
202     /**
203      * Creates a thread pool that can schedule commands to run after a
204      * given delay, or to execute periodically.
205      * @param corePoolSize the number of threads to keep in the pool,
206      * even if they are idle.
207      * @param threadFactory the factory to use when the executor
208      * creates a new thread.
209      * @return a newly created scheduled thread pool
210      */

211     public static ScheduledExecutorService JavaDoc newScheduledThreadPool(
212             int corePoolSize, ThreadFactory JavaDoc threadFactory) {
213         return new ScheduledThreadPoolExecutor JavaDoc(corePoolSize, threadFactory);
214     }
215
216
217     /**
218      * Returns an object that delegates all defined {@link
219      * ExecutorService} methods to the given executor, but not any
220      * other methods that might otherwise be accessible using
221      * casts. This provides a way to safely "freeze" configuration and
222      * disallow tuning of a given concrete implementation.
223      * @param executor the underlying implementation
224      * @return an <tt>ExecutorService</tt> instance
225      * @throws NullPointerException if executor null
226      */

227     public static ExecutorService JavaDoc unconfigurableExecutorService(ExecutorService JavaDoc executor) {
228         if (executor == null)
229             throw new NullPointerException JavaDoc();
230         return new DelegatedExecutorService(executor);
231     }
232
233     /**
234      * Returns an object that delegates all defined {@link
235      * ScheduledExecutorService} methods to the given executor, but
236      * not any other methods that might otherwise be accessible using
237      * casts. This provides a way to safely "freeze" configuration and
238      * disallow tuning of a given concrete implementation.
239      * @param executor the underlying implementation
240      * @return a <tt>ScheduledExecutorService</tt> instance
241      * @throws NullPointerException if executor null
242      */

243     public static ScheduledExecutorService JavaDoc unconfigurableScheduledExecutorService(ScheduledExecutorService JavaDoc executor) {
244         if (executor == null)
245             throw new NullPointerException JavaDoc();
246         return new DelegatedScheduledExecutorService(executor);
247     }
248         
249     /**
250      * Returns a default thread factory used to create new threads.
251      * This factory creates all new threads used by an Executor in the
252      * same {@link ThreadGroup}. If there is a {@link
253      * java.lang.SecurityManager}, it uses the group of {@link
254      * System#getSecurityManager}, else the group of the thread
255      * invoking this <tt>defaultThreadFactory</tt> method. Each new
256      * thread is created as a non-daemon thread with priority
257      * <tt>Thread.NORM_PRIORITY</tt>. New threads have names
258      * accessible via {@link Thread#getName} of
259      * <em>pool-N-thread-M</em>, where <em>N</em> is the sequence
260      * number of this factory, and <em>M</em> is the sequence number
261      * of the thread created by this factory.
262      * @return a thread factory
263      */

264     public static ThreadFactory JavaDoc defaultThreadFactory() {
265         return new DefaultThreadFactory();
266     }
267
268     /**
269      * Returns a thread factory used to create new threads that
270      * have the same permissions as the current thread.
271      * This factory creates threads with the same settings as {@link
272      * Executors#defaultThreadFactory}, additionally setting the
273      * AccessControlContext and contextClassLoader of new threads to
274      * be the same as the thread invoking this
275      * <tt>privilegedThreadFactory</tt> method. A new
276      * <tt>privilegedThreadFactory</tt> can be created within an
277      * {@link AccessController#doPrivileged} action setting the
278      * current thread's access control context to create threads with
279      * the selected permission settings holding within that action.
280      *
281      * <p> Note that while tasks running within such threads will have
282      * the same access control and class loader settings as the
283      * current thread, they need not have the same {@link
284      * java.lang.ThreadLocal} or {@link
285      * java.lang.InheritableThreadLocal} values. If necessary,
286      * particular values of thread locals can be set or reset before
287      * any task runs in {@link ThreadPoolExecutor} subclasses using
288      * {@link ThreadPoolExecutor#beforeExecute}. Also, if it is
289      * necessary to initialize worker threads to have the same
290      * InheritableThreadLocal settings as some other designated
291      * thread, you can create a custom ThreadFactory in which that
292      * thread waits for and services requests to create others that
293      * will inherit its values.
294      *
295      * @return a thread factory
296      * @throws AccessControlException if the current access control
297      * context does not have permission to both get and set context
298      * class loader.
299      */

300     public static ThreadFactory JavaDoc privilegedThreadFactory() {
301         return new PrivilegedThreadFactory();
302     }
303
304     /**
305      * Returns a {@link Callable} object that, when
306      * called, runs the given task and returns the given result. This
307      * can be useful when applying methods requiring a
308      * <tt>Callable</tt> to an otherwise resultless action.
309      * @param task the task to run
310      * @param result the result to return
311      * @throws NullPointerException if task null
312      * @return a callable object
313      */

314     public static <T> Callable JavaDoc<T> callable(Runnable JavaDoc task, T result) {
315         if (task == null)
316             throw new NullPointerException JavaDoc();
317         return new RunnableAdapter<T>(task, result);
318     }
319
320     /**
321      * Returns a {@link Callable} object that, when
322      * called, runs the given task and returns <tt>null</tt>.
323      * @param task the task to run
324      * @return a callable object
325      * @throws NullPointerException if task null
326      */

327     public static Callable JavaDoc<Object JavaDoc> callable(Runnable JavaDoc task) {
328         if (task == null)
329             throw new NullPointerException JavaDoc();
330         return new RunnableAdapter<Object JavaDoc>(task, null);
331     }
332
333     /**
334      * Returns a {@link Callable} object that, when
335      * called, runs the given privileged action and returns its result.
336      * @param action the privileged action to run
337      * @return a callable object
338      * @throws NullPointerException if action null
339      */

340     public static Callable JavaDoc<Object JavaDoc> callable(PrivilegedAction JavaDoc action) {
341         if (action == null)
342             throw new NullPointerException JavaDoc();
343         return new PrivilegedActionAdapter(action);
344     }
345
346     /**
347      * Returns a {@link Callable} object that, when
348      * called, runs the given privileged exception action and returns
349      * its result.
350      * @param action the privileged exception action to run
351      * @return a callable object
352      * @throws NullPointerException if action null
353      */

354     public static Callable JavaDoc<Object JavaDoc> callable(PrivilegedExceptionAction JavaDoc action) {
355         if (action == null)
356             throw new NullPointerException JavaDoc();
357         return new PrivilegedExceptionActionAdapter(action);
358     }
359
360     /**
361      * Returns a {@link Callable} object that will, when
362      * called, execute the given <tt>callable</tt> under the current
363      * access control context. This method should normally be
364      * invoked within an {@link AccessController#doPrivileged} action
365      * to create callables that will, if possible, execute under the
366      * selected permission settings holding within that action; or if
367      * not possible, throw an associated {@link
368      * AccessControlException}.
369      * @param callable the underlying task
370      * @return a callable object
371      * @throws NullPointerException if callable null
372      *
373      */

374     public static <T> Callable JavaDoc<T> privilegedCallable(Callable JavaDoc<T> callable) {
375         if (callable == null)
376             throw new NullPointerException JavaDoc();
377         return new PrivilegedCallable(callable);
378     }
379     
380     /**
381      * Returns a {@link Callable} object that will, when
382      * called, execute the given <tt>callable</tt> under the current
383      * access control context, with the current context class loader
384      * as the context class loader. This method should normally be
385      * invoked within an {@link AccessController#doPrivileged} action
386      * to create callables that will, if possible, execute under the
387      * selected permission settings holding within that action; or if
388      * not possible, throw an associated {@link
389      * AccessControlException}.
390      * @param callable the underlying task
391      *
392      * @return a callable object
393      * @throws NullPointerException if callable null
394      * @throws AccessControlException if the current access control
395      * context does not have permission to both set and get context
396      * class loader.
397      */

398     public static <T> Callable JavaDoc<T> privilegedCallableUsingCurrentClassLoader(Callable JavaDoc<T> callable) {
399         if (callable == null)
400             throw new NullPointerException JavaDoc();
401         return new PrivilegedCallableUsingCurrentClassLoader(callable);
402     }
403
404     // Non-public classes supporting the public methods
405

406     /**
407      * A callable that runs given task and returns given result
408      */

409     static final class RunnableAdapter<T> implements Callable JavaDoc<T> {
410         final Runnable JavaDoc task;
411         final T result;
412         RunnableAdapter(Runnable JavaDoc task, T result) {
413             this.task = task;
414             this.result = result;
415         }
416         public T call() {
417             task.run();
418             return result;
419         }
420     }
421
422     /**
423      * A callable that runs given privileged action and returns its result
424      */

425     static final class PrivilegedActionAdapter implements Callable JavaDoc<Object JavaDoc> {
426         PrivilegedActionAdapter(PrivilegedAction JavaDoc action) {
427             this.action = action;
428         }
429         public Object JavaDoc call () {
430             return action.run();
431         }
432         private final PrivilegedAction JavaDoc action;
433     }
434
435     /**
436      * A callable that runs given privileged exception action and returns its result
437      */

438     static final class PrivilegedExceptionActionAdapter implements Callable JavaDoc<Object JavaDoc> {
439         PrivilegedExceptionActionAdapter(PrivilegedExceptionAction JavaDoc action) {
440             this.action = action;
441         }
442         public Object JavaDoc call () throws Exception JavaDoc {
443             return action.run();
444         }
445         private final PrivilegedExceptionAction JavaDoc action;
446     }
447
448
449     /**
450      * A callable that runs under established access control settings
451      */

452     static final class PrivilegedCallable<T> implements Callable JavaDoc<T> {
453         private final AccessControlContext JavaDoc acc;
454         private final Callable JavaDoc<T> task;
455         private T result;
456         private Exception JavaDoc exception;
457         PrivilegedCallable(Callable JavaDoc<T> task) {
458             this.task = task;
459             this.acc = AccessController.getContext();
460         }
461
462         public T call() throws Exception JavaDoc {
463             AccessController.doPrivileged(new PrivilegedAction JavaDoc() {
464                     public Object JavaDoc run() {
465                         try {
466                             result = task.call();
467                         } catch(Exception JavaDoc ex) {
468                             exception = ex;
469                         }
470                         return null;
471                     }
472                 }, acc);
473             if (exception != null)
474                 throw exception;
475             else
476                 return result;
477         }
478     }
479
480     /**
481      * A callable that runs under established access control settings and
482      * current ClassLoader
483      */

484     static final class PrivilegedCallableUsingCurrentClassLoader<T> implements Callable JavaDoc<T> {
485         private final ClassLoader JavaDoc ccl;
486         private final AccessControlContext JavaDoc acc;
487         private final Callable JavaDoc<T> task;
488         private T result;
489         private Exception JavaDoc exception;
490         PrivilegedCallableUsingCurrentClassLoader(Callable JavaDoc<T> task) {
491             this.task = task;
492             this.ccl = Thread.currentThread().getContextClassLoader();
493             this.acc = AccessController.getContext();
494             acc.checkPermission(new RuntimePermission JavaDoc("getContextClassLoader"));
495             acc.checkPermission(new RuntimePermission JavaDoc("setContextClassLoader"));
496         }
497
498         public T call() throws Exception JavaDoc {
499             AccessController.doPrivileged(new PrivilegedAction JavaDoc() {
500                     public Object JavaDoc run() {
501                         ClassLoader JavaDoc savedcl = null;
502                         Thread JavaDoc t = Thread.currentThread();
503                         try {
504                             ClassLoader JavaDoc cl = t.getContextClassLoader();
505                             if (ccl != cl) {
506                                 t.setContextClassLoader(ccl);
507                                 savedcl = cl;
508                             }
509                             result = task.call();
510                         } catch(Exception JavaDoc ex) {
511                             exception = ex;
512                         } finally {
513                             if (savedcl != null)
514                                 t.setContextClassLoader(savedcl);
515                         }
516                         return null;
517                     }
518                 }, acc);
519             if (exception != null)
520                 throw exception;
521             else
522                 return result;
523         }
524     }
525
526     /**
527      * The default thread factory
528      */

529     static class DefaultThreadFactory implements ThreadFactory JavaDoc {
530         static final AtomicInteger JavaDoc poolNumber = new AtomicInteger JavaDoc(1);
531         final ThreadGroup JavaDoc group;
532         final AtomicInteger JavaDoc threadNumber = new AtomicInteger JavaDoc(1);
533         final String JavaDoc namePrefix;
534
535         DefaultThreadFactory() {
536             SecurityManager JavaDoc s = System.getSecurityManager();
537             group = (s != null)? s.getThreadGroup() :
538                                  Thread.currentThread().getThreadGroup();
539             namePrefix = "pool-" +
540                           poolNumber.getAndIncrement() +
541                          "-thread-";
542         }
543
544         public Thread JavaDoc newThread(Runnable JavaDoc r) {
545             Thread JavaDoc t = new Thread JavaDoc(group, r,
546                                   namePrefix + threadNumber.getAndIncrement(),
547                                   0);
548             if (t.isDaemon())
549                 t.setDaemon(false);
550             if (t.getPriority() != Thread.NORM_PRIORITY)
551                 t.setPriority(Thread.NORM_PRIORITY);
552             return t;
553         }
554     }
555
556     /**
557      * Thread factory capturing access control and class loader
558      */

559     static class PrivilegedThreadFactory extends DefaultThreadFactory {
560         private final ClassLoader JavaDoc ccl;
561         private final AccessControlContext JavaDoc acc;
562
563         PrivilegedThreadFactory() {
564             super();
565             this.ccl = Thread.currentThread().getContextClassLoader();
566             this.acc = AccessController.getContext();
567             acc.checkPermission(new RuntimePermission JavaDoc("setContextClassLoader"));
568         }
569         
570         public Thread JavaDoc newThread(final Runnable JavaDoc r) {
571             return super.newThread(new Runnable JavaDoc() {
572                 public void run() {
573                     AccessController.doPrivileged(new PrivilegedAction JavaDoc() {
574                         public Object JavaDoc run() {
575                             Thread.currentThread().setContextClassLoader(ccl);
576                             r.run();
577                             return null;
578                         }
579                     }, acc);
580                 }
581             });
582         }
583         
584     }
585
586    /**
587      * A wrapper class that exposes only the ExecutorService methods
588      * of an implementation.
589      */

590     static class DelegatedExecutorService extends AbstractExecutorService JavaDoc {
591         private final ExecutorService JavaDoc e;
592         DelegatedExecutorService(ExecutorService JavaDoc executor) { e = executor; }
593         public void execute(Runnable JavaDoc command) { e.execute(command); }
594         public void shutdown() { e.shutdown(); }
595         public List<Runnable JavaDoc> shutdownNow() { return e.shutdownNow(); }
596         public boolean isShutdown() { return e.isShutdown(); }
597         public boolean isTerminated() { return e.isTerminated(); }
598         public boolean awaitTermination(long timeout, TimeUnit JavaDoc unit)
599             throws InterruptedException JavaDoc {
600             return e.awaitTermination(timeout, unit);
601         }
602         public Future JavaDoc<?> submit(Runnable JavaDoc task) {
603             return e.submit(task);
604         }
605         public <T> Future JavaDoc<T> submit(Callable JavaDoc<T> task) {
606             return e.submit(task);
607         }
608         public <T> Future JavaDoc<T> submit(Runnable JavaDoc task, T result) {
609             return e.submit(task, result);
610         }
611         public <T> List<Future JavaDoc<T>> invokeAll(Collection<Callable JavaDoc<T>> tasks)
612             throws InterruptedException JavaDoc {
613             return e.invokeAll(tasks);
614         }
615         public <T> List<Future JavaDoc<T>> invokeAll(Collection<Callable JavaDoc<T>> tasks,
616                                              long timeout, TimeUnit JavaDoc unit)
617             throws InterruptedException JavaDoc {
618             return e.invokeAll(tasks, timeout, unit);
619         }
620         public <T> T invokeAny(Collection<Callable JavaDoc<T>> tasks)
621             throws InterruptedException JavaDoc, ExecutionException JavaDoc {
622             return e.invokeAny(tasks);
623         }
624         public <T> T invokeAny(Collection<Callable JavaDoc<T>> tasks,
625                                long timeout, TimeUnit JavaDoc unit)
626             throws InterruptedException JavaDoc, ExecutionException JavaDoc, TimeoutException JavaDoc {
627             return e.invokeAny(tasks, timeout, unit);
628         }
629     }
630     
631     /**
632      * A wrapper class that exposes only the ExecutorService and
633      * ScheduleExecutor methods of a ScheduledExecutorService implementation.
634      */

635     static class DelegatedScheduledExecutorService
636             extends DelegatedExecutorService
637             implements ScheduledExecutorService JavaDoc {
638         private final ScheduledExecutorService JavaDoc e;
639         DelegatedScheduledExecutorService(ScheduledExecutorService JavaDoc executor) {
640             super(executor);
641             e = executor;
642         }
643         public ScheduledFuture JavaDoc<?> schedule(Runnable JavaDoc command, long delay, TimeUnit JavaDoc unit) {
644             return e.schedule(command, delay, unit);
645         }
646         public <V> ScheduledFuture JavaDoc<V> schedule(Callable JavaDoc<V> callable, long delay, TimeUnit JavaDoc unit) {
647             return e.schedule(callable, delay, unit);
648         }
649         public ScheduledFuture JavaDoc<?> scheduleAtFixedRate(Runnable JavaDoc command, long initialDelay, long period, TimeUnit JavaDoc unit) {
650             return e.scheduleAtFixedRate(command, initialDelay, period, unit);
651         }
652         public ScheduledFuture JavaDoc<?> scheduleWithFixedDelay(Runnable JavaDoc command, long initialDelay, long delay, TimeUnit JavaDoc unit) {
653             return e.scheduleWithFixedDelay(command, initialDelay, delay, unit);
654         }
655     }
656
657         
658     /** Cannot instantiate. */
659     private Executors() {}
660 }
661
Popular Tags