Home | History | Annotate | Download | only in concurrent
      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      */
     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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    356     public static ThreadFactory defaultThreadFactory() {
    357         return new DefaultThreadFactory();
    358     }
    359 
    360     /**
    361      * Legacy security code; do not use.
    362      */
    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      */
    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      */
    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      */
    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