ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/main/java/util/concurrent/Executors.java
Revision: 1.44
Committed: Thu Dec 25 19:57:45 2003 UTC (20 years, 5 months ago) by dl
Branch: MAIN
Changes since 1.43: +9 -9 lines
Log Message:
Declare inner classes as private

File Contents

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