1 /*
2  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
3  *
4  * This code is free software; you can redistribute it and/or modify it
5  * under the terms of the GNU General Public License version 2 only, as
6  * published by the Free Software Foundation.  Oracle designates this
7  * particular file as subject to the "Classpath" exception as provided
8  * by Oracle in the LICENSE file that accompanied this code.
9  *
10  * This code is distributed in the hope that it will be useful, but WITHOUT
11  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
13  * version 2 for more details (a copy is included in the LICENSE file that
14  * accompanied this code).
15  *
16  * You should have received a copy of the GNU General Public License version
17  * 2 along with this work; if not, write to the Free Software Foundation,
18  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
19  *
20  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
21  * or visit www.oracle.com if you need additional information or have any
22  * questions.
23  */
24 
25 /*
26  * This file is available under and governed by the GNU General Public
27  * License version 2 only, as published by the Free Software Foundation.
28  * However, the following notice accompanied the original version of this
29  * file:
30  *
31  * Written by Doug Lea with assistance from members of JCP JSR-166
32  * Expert Group and released to the public domain, as explained at
33  * http://creativecommons.org/publicdomain/zero/1.0/
34  */
35 
36 package java.util.concurrent;
37 
38 import java.security.AccessControlContext;
39 import java.security.AccessControlException;
40 import java.security.AccessController;
41 import java.security.PrivilegedAction;
42 import java.security.PrivilegedActionException;
43 import java.security.PrivilegedExceptionAction;
44 import java.util.Collection;
45 import java.util.List;
46 import java.util.concurrent.atomic.AtomicInteger;
47 import sun.security.util.SecurityConstants;
48 
49 // BEGIN android-note
50 // removed security manager docs
51 // END android-note
52 
53 /**
54  * Factory and utility methods for {@link Executor}, {@link
55  * ExecutorService}, {@link ScheduledExecutorService}, {@link
56  * ThreadFactory}, and {@link Callable} classes defined in this
57  * package. This class supports the following kinds of methods:
58  *
59  * <ul>
60  *   <li>Methods that create and return an {@link ExecutorService}
61  *       set up with commonly useful configuration settings.
62  *   <li>Methods that create and return a {@link ScheduledExecutorService}
63  *       set up with commonly useful configuration settings.
64  *   <li>Methods that create and return a "wrapped" ExecutorService, that
65  *       disables reconfiguration by making implementation-specific methods
66  *       inaccessible.
67  *   <li>Methods that create and return a {@link ThreadFactory}
68  *       that sets newly created threads to a known state.
69  *   <li>Methods that create and return a {@link Callable}
70  *       out of other closure-like forms, so they can be used
71  *       in execution methods requiring {@code Callable}.
72  * </ul>
73  *
74  * @since 1.5
75  * @author Doug Lea
76  */
77 public class Executors {
78 
79     /**
80      * Creates a thread pool that reuses a fixed number of threads
81      * operating off a shared unbounded queue.  At any point, at most
82      * {@code nThreads} threads will be active processing tasks.
83      * If additional tasks are submitted when all threads are active,
84      * they will wait in the queue until a thread is available.
85      * If any thread terminates due to a failure during execution
86      * prior to shutdown, a new one will take its place if needed to
87      * execute subsequent tasks.  The threads in the pool will exist
88      * until it is explicitly {@link ExecutorService#shutdown shutdown}.
89      *
90      * @param nThreads the number of threads in the pool
91      * @return the newly created thread pool
92      * @throws IllegalArgumentException if {@code nThreads <= 0}
93      */
newFixedThreadPool(int nThreads)94     public static ExecutorService newFixedThreadPool(int nThreads) {
95         return new ThreadPoolExecutor(nThreads, nThreads,
96                                       0L, TimeUnit.MILLISECONDS,
97                                       new LinkedBlockingQueue<Runnable>());
98     }
99 
100     /**
101      * Creates a thread pool that maintains enough threads to support
102      * the given parallelism level, and may use multiple queues to
103      * reduce contention. The parallelism level corresponds to the
104      * maximum number of threads actively engaged in, or available to
105      * engage in, task processing. The actual number of threads may
106      * grow and shrink dynamically. A work-stealing pool makes no
107      * guarantees about the order in which submitted tasks are
108      * executed.
109      *
110      * @param parallelism the targeted parallelism level
111      * @return the newly created thread pool
112      * @throws IllegalArgumentException if {@code parallelism <= 0}
113      * @since 1.8
114      */
newWorkStealingPool(int parallelism)115     public static ExecutorService newWorkStealingPool(int parallelism) {
116         return new ForkJoinPool
117             (parallelism,
118              ForkJoinPool.defaultForkJoinWorkerThreadFactory,
119              null, true);
120     }
121 
122     /**
123      * Creates a work-stealing thread pool using the number of
124      * {@linkplain Runtime#availableProcessors available processors}
125      * as its target parallelism level.
126      *
127      * @return the newly created thread pool
128      * @see #newWorkStealingPool(int)
129      * @since 1.8
130      */
newWorkStealingPool()131     public static ExecutorService newWorkStealingPool() {
132         return new ForkJoinPool
133             (Runtime.getRuntime().availableProcessors(),
134              ForkJoinPool.defaultForkJoinWorkerThreadFactory,
135              null, true);
136     }
137 
138     /**
139      * Creates a thread pool that reuses a fixed number of threads
140      * operating off a shared unbounded queue, using the provided
141      * ThreadFactory to create new threads when needed.  At any point,
142      * at most {@code nThreads} threads will be active processing
143      * tasks.  If additional tasks are submitted when all threads are
144      * active, they will wait in the queue until a thread is
145      * available.  If any thread terminates due to a failure during
146      * execution prior to shutdown, a new one will take its place if
147      * needed to execute subsequent tasks.  The threads in the pool will
148      * exist until it is explicitly {@link ExecutorService#shutdown
149      * shutdown}.
150      *
151      * @param nThreads the number of threads in the pool
152      * @param threadFactory the factory to use when creating new threads
153      * @return the newly created thread pool
154      * @throws NullPointerException if threadFactory is null
155      * @throws IllegalArgumentException if {@code nThreads <= 0}
156      */
newFixedThreadPool(int nThreads, ThreadFactory threadFactory)157     public static ExecutorService newFixedThreadPool(int nThreads, ThreadFactory threadFactory) {
158         return new ThreadPoolExecutor(nThreads, nThreads,
159                                       0L, TimeUnit.MILLISECONDS,
160                                       new LinkedBlockingQueue<Runnable>(),
161                                       threadFactory);
162     }
163 
164     /**
165      * Creates an Executor that uses a single worker thread operating
166      * off an unbounded queue. (Note however that if this single
167      * thread terminates due to a failure during execution prior to
168      * shutdown, a new one will take its place if needed to execute
169      * subsequent tasks.)  Tasks are guaranteed to execute
170      * sequentially, and no more than one task will be active at any
171      * given time. Unlike the otherwise equivalent
172      * {@code newFixedThreadPool(1)} the returned executor is
173      * guaranteed not to be reconfigurable to use additional threads.
174      *
175      * @return the newly created single-threaded Executor
176      */
newSingleThreadExecutor()177     public static ExecutorService newSingleThreadExecutor() {
178         return new FinalizableDelegatedExecutorService
179             (new ThreadPoolExecutor(1, 1,
180                                     0L, TimeUnit.MILLISECONDS,
181                                     new LinkedBlockingQueue<Runnable>()));
182     }
183 
184     /**
185      * Creates an Executor that uses a single worker thread operating
186      * off an unbounded queue, and uses the provided ThreadFactory to
187      * create a new thread when needed. Unlike the otherwise
188      * equivalent {@code newFixedThreadPool(1, threadFactory)} the
189      * returned executor is guaranteed not to be reconfigurable to use
190      * additional threads.
191      *
192      * @param threadFactory the factory to use when creating new
193      * threads
194      *
195      * @return the newly created single-threaded Executor
196      * @throws NullPointerException if threadFactory is null
197      */
newSingleThreadExecutor(ThreadFactory threadFactory)198     public static ExecutorService newSingleThreadExecutor(ThreadFactory threadFactory) {
199         return new FinalizableDelegatedExecutorService
200             (new ThreadPoolExecutor(1, 1,
201                                     0L, TimeUnit.MILLISECONDS,
202                                     new LinkedBlockingQueue<Runnable>(),
203                                     threadFactory));
204     }
205 
206     /**
207      * Creates a thread pool that creates new threads as needed, but
208      * will reuse previously constructed threads when they are
209      * available.  These pools will typically improve the performance
210      * of programs that execute many short-lived asynchronous tasks.
211      * Calls to {@code execute} will reuse previously constructed
212      * threads if available. If no existing thread is available, a new
213      * thread will be created and added to the pool. Threads that have
214      * not been used for sixty seconds are terminated and removed from
215      * the cache. Thus, a pool that remains idle for long enough will
216      * not consume any resources. Note that pools with similar
217      * properties but different details (for example, timeout parameters)
218      * may be created using {@link ThreadPoolExecutor} constructors.
219      *
220      * @return the newly created thread pool
221      */
newCachedThreadPool()222     public static ExecutorService newCachedThreadPool() {
223         return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
224                                       60L, TimeUnit.SECONDS,
225                                       new SynchronousQueue<Runnable>());
226     }
227 
228     /**
229      * Creates a thread pool that creates new threads as needed, but
230      * will reuse previously constructed threads when they are
231      * available, and uses the provided
232      * ThreadFactory to create new threads when needed.
233      * @param threadFactory the factory to use when creating new threads
234      * @return the newly created thread pool
235      * @throws NullPointerException if threadFactory is null
236      */
newCachedThreadPool(ThreadFactory threadFactory)237     public static ExecutorService newCachedThreadPool(ThreadFactory threadFactory) {
238         return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
239                                       60L, TimeUnit.SECONDS,
240                                       new SynchronousQueue<Runnable>(),
241                                       threadFactory);
242     }
243 
244     /**
245      * Creates a single-threaded executor that can schedule commands
246      * to run after a given delay, or to execute periodically.
247      * (Note however that if this single
248      * thread terminates due to a failure during execution prior to
249      * shutdown, a new one will take its place if needed to execute
250      * subsequent tasks.)  Tasks are guaranteed to execute
251      * sequentially, and no more than one task will be active at any
252      * given time. Unlike the otherwise equivalent
253      * {@code newScheduledThreadPool(1)} the returned executor is
254      * guaranteed not to be reconfigurable to use additional threads.
255      * @return the newly created scheduled executor
256      */
newSingleThreadScheduledExecutor()257     public static ScheduledExecutorService newSingleThreadScheduledExecutor() {
258         return new DelegatedScheduledExecutorService
259             (new ScheduledThreadPoolExecutor(1));
260     }
261 
262     /**
263      * Creates a single-threaded executor that can schedule commands
264      * to run after a given delay, or to execute periodically.  (Note
265      * however that if this single thread terminates due to a failure
266      * during execution prior to shutdown, a new one will take its
267      * place if needed to execute subsequent tasks.)  Tasks are
268      * guaranteed to execute sequentially, and no more than one task
269      * will be active at any given time. Unlike the otherwise
270      * equivalent {@code newScheduledThreadPool(1, threadFactory)}
271      * the returned executor is guaranteed not to be reconfigurable to
272      * use additional threads.
273      * @param threadFactory the factory to use when creating new
274      * threads
275      * @return a newly created scheduled executor
276      * @throws NullPointerException if threadFactory is null
277      */
newSingleThreadScheduledExecutor(ThreadFactory threadFactory)278     public static ScheduledExecutorService newSingleThreadScheduledExecutor(ThreadFactory threadFactory) {
279         return new DelegatedScheduledExecutorService
280             (new ScheduledThreadPoolExecutor(1, threadFactory));
281     }
282 
283     /**
284      * Creates a thread pool that can schedule commands to run after a
285      * given delay, or to execute periodically.
286      * @param corePoolSize the number of threads to keep in the pool,
287      * even if they are idle
288      * @return a newly created scheduled thread pool
289      * @throws IllegalArgumentException if {@code corePoolSize < 0}
290      */
newScheduledThreadPool(int corePoolSize)291     public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {
292         return new ScheduledThreadPoolExecutor(corePoolSize);
293     }
294 
295     /**
296      * Creates a thread pool that can schedule commands to run after a
297      * given delay, or to execute periodically.
298      * @param corePoolSize the number of threads to keep in the pool,
299      * even if they are idle
300      * @param threadFactory the factory to use when the executor
301      * creates a new thread
302      * @return a newly created scheduled thread pool
303      * @throws IllegalArgumentException if {@code corePoolSize < 0}
304      * @throws NullPointerException if threadFactory is null
305      */
newScheduledThreadPool( int corePoolSize, ThreadFactory threadFactory)306     public static ScheduledExecutorService newScheduledThreadPool(
307             int corePoolSize, ThreadFactory threadFactory) {
308         return new ScheduledThreadPoolExecutor(corePoolSize, threadFactory);
309     }
310 
311     /**
312      * Returns an object that delegates all defined {@link
313      * ExecutorService} methods to the given executor, but not any
314      * other methods that might otherwise be accessible using
315      * casts. This provides a way to safely "freeze" configuration and
316      * disallow tuning of a given concrete implementation.
317      * @param executor the underlying implementation
318      * @return an {@code ExecutorService} instance
319      * @throws NullPointerException if executor null
320      */
unconfigurableExecutorService(ExecutorService executor)321     public static ExecutorService unconfigurableExecutorService(ExecutorService executor) {
322         if (executor == null)
323             throw new NullPointerException();
324         return new DelegatedExecutorService(executor);
325     }
326 
327     /**
328      * Returns an object that delegates all defined {@link
329      * ScheduledExecutorService} methods to the given executor, but
330      * not any other methods that might otherwise be accessible using
331      * casts. This provides a way to safely "freeze" configuration and
332      * disallow tuning of a given concrete implementation.
333      * @param executor the underlying implementation
334      * @return a {@code ScheduledExecutorService} instance
335      * @throws NullPointerException if executor null
336      */
unconfigurableScheduledExecutorService(ScheduledExecutorService executor)337     public static ScheduledExecutorService unconfigurableScheduledExecutorService(ScheduledExecutorService executor) {
338         if (executor == null)
339             throw new NullPointerException();
340         return new DelegatedScheduledExecutorService(executor);
341     }
342 
343     /**
344      * Returns a default thread factory used to create new threads.
345      * This factory creates all new threads used by an Executor in the
346      * same {@link ThreadGroup}. Each new
347      * thread is created as a non-daemon thread with priority set to
348      * the smaller of {@code Thread.NORM_PRIORITY} and the maximum
349      * priority permitted in the thread group.  New threads have names
350      * accessible via {@link Thread#getName} of
351      * <em>pool-N-thread-M</em>, where <em>N</em> is the sequence
352      * number of this factory, and <em>M</em> is the sequence number
353      * of the thread created by this factory.
354      * @return a thread factory
355      */
defaultThreadFactory()356     public static ThreadFactory defaultThreadFactory() {
357         return new DefaultThreadFactory();
358     }
359 
360     /**
361      * Legacy security code; do not use.
362      */
privilegedThreadFactory()363     public static ThreadFactory privilegedThreadFactory() {
364         return new PrivilegedThreadFactory();
365     }
366 
367     /**
368      * Returns a {@link Callable} object that, when
369      * called, runs the given task and returns the given result.  This
370      * can be useful when applying methods requiring a
371      * {@code Callable} to an otherwise resultless action.
372      * @param task the task to run
373      * @param result the result to return
374      * @param <T> the type of the result
375      * @return a callable object
376      * @throws NullPointerException if task null
377      */
callable(Runnable task, T result)378     public static <T> Callable<T> callable(Runnable task, T result) {
379         if (task == null)
380             throw new NullPointerException();
381         return new RunnableAdapter<T>(task, result);
382     }
383 
384     /**
385      * Returns a {@link Callable} object that, when
386      * called, runs the given task and returns {@code null}.
387      * @param task the task to run
388      * @return a callable object
389      * @throws NullPointerException if task null
390      */
callable(Runnable task)391     public static Callable<Object> callable(Runnable task) {
392         if (task == null)
393             throw new NullPointerException();
394         return new RunnableAdapter<Object>(task, null);
395     }
396 
397     /**
398      * Returns a {@link Callable} object that, when
399      * called, runs the given privileged action and returns its result.
400      * @param action the privileged action to run
401      * @return a callable object
402      * @throws NullPointerException if action null
403      */
callable(final PrivilegedAction<?> action)404     public static Callable<Object> callable(final PrivilegedAction<?> action) {
405         if (action == null)
406             throw new NullPointerException();
407         return new Callable<Object>() {
408             public Object call() { return action.run(); }};
409     }
410 
411     /**
412      * Returns a {@link Callable} object that, when
413      * called, runs the given privileged exception action and returns
414      * its result.
415      * @param action the privileged exception action to run
416      * @return a callable object
417      * @throws NullPointerException if action null
418      */
419     public static Callable<Object> callable(final PrivilegedExceptionAction<?> action) {
420         if (action == null)
421             throw new NullPointerException();
422         return new Callable<Object>() {
423             public Object call() throws Exception { return action.run(); }};
424     }
425 
426     /**
427      * Legacy security code; do not use.
428      */
429     public static <T> Callable<T> privilegedCallable(Callable<T> callable) {
430         if (callable == null)
431             throw new NullPointerException();
432         return new PrivilegedCallable<T>(callable);
433     }
434 
435     /**
436      * Legacy security code; do not use.
437      */
438     public static <T> Callable<T> privilegedCallableUsingCurrentClassLoader(Callable<T> callable) {
439         if (callable == null)
440             throw new NullPointerException();
441         return new PrivilegedCallableUsingCurrentClassLoader<T>(callable);
442     }
443 
444     // Non-public classes supporting the public methods
445 
446     /**
447      * A callable that runs given task and returns given result.
448      */
449     private static final class RunnableAdapter<T> implements Callable<T> {
450         private final Runnable task;
451         private final T result;
452         RunnableAdapter(Runnable task, T result) {
453             this.task = task;
454             this.result = result;
455         }
456         public T call() {
457             task.run();
458             return result;
459         }
460     }
461 
462     /**
463      * A callable that runs under established access control settings.
464      */
465     private static final class PrivilegedCallable<T> implements Callable<T> {
466         final Callable<T> task;
467         final AccessControlContext acc;
468 
469         PrivilegedCallable(Callable<T> task) {
470             this.task = task;
471             this.acc = AccessController.getContext();
472         }
473 
474         public T call() throws Exception {
475             try {
476                 return AccessController.doPrivileged(
477                     new PrivilegedExceptionAction<T>() {
478                         public T run() throws Exception {
479                             return task.call();
480                         }
481                     }, acc);
482             } catch (PrivilegedActionException e) {
483                 throw e.getException();
484             }
485         }
486     }
487 
488     /**
489      * A callable that runs under established access control settings and
490      * current ClassLoader.
491      */
492     private static final class PrivilegedCallableUsingCurrentClassLoader<T>
493             implements Callable<T> {
494         final Callable<T> task;
495         final AccessControlContext acc;
496         final ClassLoader ccl;
497 
498         PrivilegedCallableUsingCurrentClassLoader(Callable<T> task) {
499             // BEGIN Android-removed
500             // SecurityManager sm = System.getSecurityManager();
501             // if (sm != null) {
502             //     // Calls to getContextClassLoader from this class
503             //     // never trigger a security check, but we check
504             //     // whether our callers have this permission anyways.
505             //     sm.checkPermission(SecurityConstants.GET_CLASSLOADER_PERMISSION);
506 
507             //     // Whether setContextClassLoader turns out to be necessary
508             //     // or not, we fail fast if permission is not available.
509             //     sm.checkPermission(new RuntimePermission("setContextClassLoader"));
510             // }
511             // END Android-removed
512             this.task = task;
513             this.acc = AccessController.getContext();
514             this.ccl = Thread.currentThread().getContextClassLoader();
515         }
516 
517         public T call() throws Exception {
518             try {
519                 return AccessController.doPrivileged(
520                     new PrivilegedExceptionAction<T>() {
521                         public T run() throws Exception {
522                             Thread t = Thread.currentThread();
523                             ClassLoader cl = t.getContextClassLoader();
524                             if (ccl == cl) {
525                                 return task.call();
526                             } else {
527                                 t.setContextClassLoader(ccl);
528                                 try {
529                                     return task.call();
530                                 } finally {
531                                     t.setContextClassLoader(cl);
532                                 }
533                             }
534                         }
535                     }, acc);
536             } catch (PrivilegedActionException e) {
537                 throw e.getException();
538             }
539         }
540     }
541 
542     /**
543      * The default thread factory.
544      */
545     private static class DefaultThreadFactory implements ThreadFactory {
546         private static final AtomicInteger poolNumber = new AtomicInteger(1);
547         private final ThreadGroup group;
548         private final AtomicInteger threadNumber = new AtomicInteger(1);
549         private final String namePrefix;
550 
551         DefaultThreadFactory() {
552             SecurityManager s = System.getSecurityManager();
553             group = (s != null) ? s.getThreadGroup() :
554                                   Thread.currentThread().getThreadGroup();
555             namePrefix = "pool-" +
556                           poolNumber.getAndIncrement() +
557                          "-thread-";
558         }
559 
560         public Thread newThread(Runnable r) {
561             Thread t = new Thread(group, r,
562                                   namePrefix + threadNumber.getAndIncrement(),
563                                   0);
564             if (t.isDaemon())
565                 t.setDaemon(false);
566             if (t.getPriority() != Thread.NORM_PRIORITY)
567                 t.setPriority(Thread.NORM_PRIORITY);
568             return t;
569         }
570     }
571 
572     /**
573      * Thread factory capturing access control context and class loader.
574      */
575     private static class PrivilegedThreadFactory extends DefaultThreadFactory {
576         final AccessControlContext acc;
577         final ClassLoader ccl;
578 
579         PrivilegedThreadFactory() {
580             super();
581             // BEGIN Android-removed
582             // SecurityManager sm = System.getSecurityManager();
583             // if (sm != null) {
584             //     // Calls to getContextClassLoader from this class
585             //     // never trigger a security check, but we check
586             //     // whether our callers have this permission anyways.
587             //     sm.checkPermission(SecurityConstants.GET_CLASSLOADER_PERMISSION);
588 
589             //     // Fail fast
590             //     sm.checkPermission(new RuntimePermission("setContextClassLoader"));
591             // }
592             // END Android-removed
593             this.acc = AccessController.getContext();
594             this.ccl = Thread.currentThread().getContextClassLoader();
595         }
596 
597         public Thread newThread(final Runnable r) {
598             return super.newThread(new Runnable() {
599                 public void run() {
600                     AccessController.doPrivileged(new PrivilegedAction<Void>() {
601                         public Void run() {
602                             Thread.currentThread().setContextClassLoader(ccl);
603                             r.run();
604                             return null;
605                         }
606                     }, acc);
607                 }
608             });
609         }
610     }
611 
612     /**
613      * A wrapper class that exposes only the ExecutorService methods
614      * of an ExecutorService implementation.
615      */
616     private static class DelegatedExecutorService
617             extends AbstractExecutorService {
618         private final ExecutorService e;
619         DelegatedExecutorService(ExecutorService executor) { e = executor; }
620         public void execute(Runnable command) { e.execute(command); }
621         public void shutdown() { e.shutdown(); }
622         public List<Runnable> shutdownNow() { return e.shutdownNow(); }
623         public boolean isShutdown() { return e.isShutdown(); }
624         public boolean isTerminated() { return e.isTerminated(); }
625         public boolean awaitTermination(long timeout, TimeUnit unit)
626             throws InterruptedException {
627             return e.awaitTermination(timeout, unit);
628         }
629         public Future<?> submit(Runnable task) {
630             return e.submit(task);
631         }
632         public <T> Future<T> submit(Callable<T> task) {
633             return e.submit(task);
634         }
635         public <T> Future<T> submit(Runnable task, T result) {
636             return e.submit(task, result);
637         }
638         public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks)
639             throws InterruptedException {
640             return e.invokeAll(tasks);
641         }
642         public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks,
643                                              long timeout, TimeUnit unit)
644             throws InterruptedException {
645             return e.invokeAll(tasks, timeout, unit);
646         }
647         public <T> T invokeAny(Collection<? extends Callable<T>> tasks)
648             throws InterruptedException, ExecutionException {
649             return e.invokeAny(tasks);
650         }
651         public <T> T invokeAny(Collection<? extends Callable<T>> tasks,
652                                long timeout, TimeUnit unit)
653             throws InterruptedException, ExecutionException, TimeoutException {
654             return e.invokeAny(tasks, timeout, unit);
655         }
656     }
657 
658     private static class FinalizableDelegatedExecutorService
659             extends DelegatedExecutorService {
660         FinalizableDelegatedExecutorService(ExecutorService executor) {
661             super(executor);
662         }
663         protected void finalize() {
664             super.shutdown();
665         }
666     }
667 
668     /**
669      * A wrapper class that exposes only the ScheduledExecutorService
670      * methods of a ScheduledExecutorService implementation.
671      */
672     private static class DelegatedScheduledExecutorService
673             extends DelegatedExecutorService
674             implements ScheduledExecutorService {
675         private final ScheduledExecutorService e;
676         DelegatedScheduledExecutorService(ScheduledExecutorService executor) {
677             super(executor);
678             e = executor;
679         }
680         public ScheduledFuture<?> schedule(Runnable command, long delay, TimeUnit unit) {
681             return e.schedule(command, delay, unit);
682         }
683         public <V> ScheduledFuture<V> schedule(Callable<V> callable, long delay, TimeUnit unit) {
684             return e.schedule(callable, delay, unit);
685         }
686         public ScheduledFuture<?> scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit) {
687             return e.scheduleAtFixedRate(command, initialDelay, period, unit);
688         }
689         public ScheduledFuture<?> scheduleWithFixedDelay(Runnable command, long initialDelay, long delay, TimeUnit unit) {
690             return e.scheduleWithFixedDelay(command, initialDelay, delay, unit);
691         }
692     }
693 
694     /** Cannot instantiate. */
695     private Executors() {}
696 }
697