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