001 /*
002 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
003 *
004 * This code is free software; you can redistribute it and/or modify it
005 * under the terms of the GNU General Public License version 2 only, as
006 * published by the Free Software Foundation. Sun designates this
007 * particular file as subject to the "Classpath" exception as provided
008 * by Sun in the LICENSE file that accompanied this code.
009 *
010 * This code is distributed in the hope that it will be useful, but WITHOUT
011 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
012 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
013 * version 2 for more details (a copy is included in the LICENSE file that
014 * accompanied this code).
015 *
016 * You should have received a copy of the GNU General Public License version
017 * 2 along with this work; if not, write to the Free Software Foundation,
018 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
019 *
020 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
021 * CA 95054 USA or visit www.sun.com if you need additional information or
022 * have any questions.
023 */
024
025 /*
026 * This file is available under and governed by the GNU General Public
027 * License version 2 only, as published by the Free Software Foundation.
028 * However, the following notice accompanied the original version of this
029 * file:
030 *
031 * Written by Doug Lea with assistance from members of JCP JSR-166
032 * Expert Group and released to the public domain, as explained at
033 * http://creativecommons.org/licenses/publicdomain
034 */
035
036 package java.util.concurrent;
037
038 import java.util.*;
039 import java.util.concurrent.atomic.AtomicInteger;
040 import java.security.AccessControlContext;
041 import java.security.AccessController;
042 import java.security.PrivilegedAction;
043 import java.security.PrivilegedExceptionAction;
044 import java.security.PrivilegedActionException;
045 import java.security.AccessControlException;
046 import sun.security.util.SecurityConstants;
047
048 /**
049 * Factory and utility methods for {@link Executor}, {@link
050 * ExecutorService}, {@link ScheduledExecutorService}, {@link
051 * ThreadFactory}, and {@link Callable} classes defined in this
052 * package. This class supports the following kinds of methods:
053 *
054 * <ul>
055 * <li> Methods that create and return an {@link ExecutorService}
056 * set up with commonly useful configuration settings.
057 * <li> Methods that create and return a {@link ScheduledExecutorService}
058 * set up with commonly useful configuration settings.
059 * <li> Methods that create and return a "wrapped" ExecutorService, that
060 * disables reconfiguration by making implementation-specific methods
061 * inaccessible.
062 * <li> Methods that create and return a {@link ThreadFactory}
063 * that sets newly created threads to a known state.
064 * <li> Methods that create and return a {@link Callable}
065 * out of other closure-like forms, so they can be used
066 * in execution methods requiring <tt>Callable</tt>.
067 * </ul>
068 *
069 * @since 1.5
070 * @author Doug Lea
071 */
072 public class Executors {
073
074 /**
075 * Creates a thread pool that reuses a fixed number of threads
076 * operating off a shared unbounded queue. At any point, at most
077 * <tt>nThreads</tt> threads will be active processing tasks.
078 * If additional tasks are submitted when all threads are active,
079 * they will wait in the queue until a thread is available.
080 * If any thread terminates due to a failure during execution
081 * prior to shutdown, a new one will take its place if needed to
082 * execute subsequent tasks. The threads in the pool will exist
083 * until it is explicitly {@link ExecutorService#shutdown shutdown}.
084 *
085 * @param nThreads the number of threads in the pool
086 * @return the newly created thread pool
087 * @throws IllegalArgumentException if <tt>nThreads <= 0</tt>
088 */
089 public static ExecutorService newFixedThreadPool(int nThreads) {
090 return new ThreadPoolExecutor(nThreads, nThreads, 0L,
091 TimeUnit.MILLISECONDS,
092 new LinkedBlockingQueue<Runnable>());
093 }
094
095 /**
096 * Creates a thread pool that reuses a fixed number of threads
097 * operating off a shared unbounded queue, using the provided
098 * ThreadFactory to create new threads when needed. At any point,
099 * at most <tt>nThreads</tt> threads will be active processing
100 * tasks. If additional tasks are submitted when all threads are
101 * active, they will wait in the queue until a thread is
102 * available. If any thread terminates due to a failure during
103 * execution prior to shutdown, a new one will take its place if
104 * needed to execute subsequent tasks. The threads in the pool will
105 * exist until it is explicitly {@link ExecutorService#shutdown
106 * shutdown}.
107 *
108 * @param nThreads the number of threads in the pool
109 * @param threadFactory the factory to use when creating new threads
110 * @return the newly created thread pool
111 * @throws NullPointerException if threadFactory is null
112 * @throws IllegalArgumentException if <tt>nThreads <= 0</tt>
113 */
114 public static ExecutorService newFixedThreadPool(int nThreads,
115 ThreadFactory threadFactory) {
116 return new ThreadPoolExecutor(nThreads, nThreads, 0L,
117 TimeUnit.MILLISECONDS,
118 new LinkedBlockingQueue<Runnable>(), threadFactory);
119 }
120
121 /**
122 * Creates an Executor that uses a single worker thread operating
123 * off an unbounded queue. (Note however that if this single
124 * thread terminates due to a failure during execution prior to
125 * shutdown, a new one will take its place if needed to execute
126 * subsequent tasks.) Tasks are guaranteed to execute
127 * sequentially, and no more than one task will be active at any
128 * given time. Unlike the otherwise equivalent
129 * <tt>newFixedThreadPool(1)</tt> the returned executor is
130 * guaranteed not to be reconfigurable to use additional threads.
131 *
132 * @return the newly created single-threaded Executor
133 */
134 public static ExecutorService newSingleThreadExecutor() {
135 return new FinalizableDelegatedExecutorService(
136 new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS,
137 new LinkedBlockingQueue<Runnable>()));
138 }
139
140 /**
141 * Creates an Executor that uses a single worker thread operating
142 * off an unbounded queue, and uses the provided ThreadFactory to
143 * create a new thread when needed. Unlike the otherwise
144 * equivalent <tt>newFixedThreadPool(1, threadFactory)</tt> the
145 * returned executor is guaranteed not to be reconfigurable to use
146 * additional threads.
147 *
148 * @param threadFactory the factory to use when creating new
149 * threads
150 *
151 * @return the newly created single-threaded Executor
152 * @throws NullPointerException if threadFactory is null
153 */
154 public static ExecutorService newSingleThreadExecutor(
155 ThreadFactory threadFactory) {
156 return new FinalizableDelegatedExecutorService(
157 new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS,
158 new LinkedBlockingQueue<Runnable>(),
159 threadFactory));
160 }
161
162 /**
163 * Creates a thread pool that creates new threads as needed, but
164 * will reuse previously constructed threads when they are
165 * available. These pools will typically improve the performance
166 * of programs that execute many short-lived asynchronous tasks.
167 * Calls to <tt>execute</tt> will reuse previously constructed
168 * threads if available. If no existing thread is available, a new
169 * thread will be created and added to the pool. Threads that have
170 * not been used for sixty seconds are terminated and removed from
171 * the cache. Thus, a pool that remains idle for long enough will
172 * not consume any resources. Note that pools with similar
173 * properties but different details (for example, timeout parameters)
174 * may be created using {@link ThreadPoolExecutor} constructors.
175 *
176 * @return the newly created thread pool
177 */
178 public static ExecutorService newCachedThreadPool() {
179 return new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60L,
180 TimeUnit.SECONDS, new SynchronousQueue<Runnable>());
181 }
182
183 /**
184 * Creates a thread pool that creates new threads as needed, but
185 * will reuse previously constructed threads when they are
186 * available, and uses the provided
187 * ThreadFactory to create new threads when needed.
188 * @param threadFactory the factory to use when creating new threads
189 * @return the newly created thread pool
190 * @throws NullPointerException if threadFactory is null
191 */
192 public static ExecutorService newCachedThreadPool(
193 ThreadFactory threadFactory) {
194 return new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60L,
195 TimeUnit.SECONDS, new SynchronousQueue<Runnable>(),
196 threadFactory);
197 }
198
199 /**
200 * Creates a single-threaded executor that can schedule commands
201 * to run after a given delay, or to execute periodically.
202 * (Note however that if this single
203 * thread terminates due to a failure during execution prior to
204 * shutdown, a new one will take its place if needed to execute
205 * subsequent tasks.) Tasks are guaranteed to execute
206 * sequentially, and no more than one task will be active at any
207 * given time. Unlike the otherwise equivalent
208 * <tt>newScheduledThreadPool(1)</tt> the returned executor is
209 * guaranteed not to be reconfigurable to use additional threads.
210 * @return the newly created scheduled executor
211 */
212 public static ScheduledExecutorService newSingleThreadScheduledExecutor() {
213 return new DelegatedScheduledExecutorService(
214 new ScheduledThreadPoolExecutor(1));
215 }
216
217 /**
218 * Creates a single-threaded executor that can schedule commands
219 * to run after a given delay, or to execute periodically. (Note
220 * however that if this single thread terminates due to a failure
221 * during execution prior to shutdown, a new one will take its
222 * place if needed to execute subsequent tasks.) Tasks are
223 * guaranteed to execute sequentially, and no more than one task
224 * will be active at any given time. Unlike the otherwise
225 * equivalent <tt>newScheduledThreadPool(1, threadFactory)</tt>
226 * the returned executor is guaranteed not to be reconfigurable to
227 * use additional threads.
228 * @param threadFactory the factory to use when creating new
229 * threads
230 * @return a newly created scheduled executor
231 * @throws NullPointerException if threadFactory is null
232 */
233 public static ScheduledExecutorService newSingleThreadScheduledExecutor(
234 ThreadFactory threadFactory) {
235 return new DelegatedScheduledExecutorService(
236 new ScheduledThreadPoolExecutor(1, threadFactory));
237 }
238
239 /**
240 * Creates a thread pool that can schedule commands to run after a
241 * given delay, or to execute periodically.
242 * @param corePoolSize the number of threads to keep in the pool,
243 * even if they are idle.
244 * @return a newly created scheduled thread pool
245 * @throws IllegalArgumentException if <tt>corePoolSize < 0</tt>
246 */
247 public static ScheduledExecutorService newScheduledThreadPool(
248 int corePoolSize) {
249 return new ScheduledThreadPoolExecutor(corePoolSize);
250 }
251
252 /**
253 * Creates a thread pool that can schedule commands to run after a
254 * given delay, or to execute periodically.
255 * @param corePoolSize the number of threads to keep in the pool,
256 * even if they are idle.
257 * @param threadFactory the factory to use when the executor
258 * creates a new thread.
259 * @return a newly created scheduled thread pool
260 * @throws IllegalArgumentException if <tt>corePoolSize < 0</tt>
261 * @throws NullPointerException if threadFactory is null
262 */
263 public static ScheduledExecutorService newScheduledThreadPool(
264 int corePoolSize, ThreadFactory threadFactory) {
265 return new ScheduledThreadPoolExecutor(corePoolSize,
266 threadFactory);
267 }
268
269 /**
270 * Returns an object that delegates all defined {@link
271 * ExecutorService} methods to the given executor, but not any
272 * other methods that might otherwise be accessible using
273 * casts. This provides a way to safely "freeze" configuration and
274 * disallow tuning of a given concrete implementation.
275 * @param executor the underlying implementation
276 * @return an <tt>ExecutorService</tt> instance
277 * @throws NullPointerException if executor null
278 */
279 public static ExecutorService unconfigurableExecutorService(
280 ExecutorService executor) {
281 if (executor == null)
282 throw new NullPointerException();
283 return new DelegatedExecutorService(executor);
284 }
285
286 /**
287 * Returns an object that delegates all defined {@link
288 * ScheduledExecutorService} methods to the given executor, but
289 * not any other methods that might otherwise be accessible using
290 * casts. This provides a way to safely "freeze" configuration and
291 * disallow tuning of a given concrete implementation.
292 * @param executor the underlying implementation
293 * @return a <tt>ScheduledExecutorService</tt> instance
294 * @throws NullPointerException if executor null
295 */
296 public static ScheduledExecutorService unconfigurableScheduledExecutorService(
297 ScheduledExecutorService executor) {
298 if (executor == null)
299 throw new NullPointerException();
300 return new DelegatedScheduledExecutorService(executor);
301 }
302
303 /**
304 * Returns a default thread factory used to create new threads.
305 * This factory creates all new threads used by an Executor in the
306 * same {@link ThreadGroup}. If there is a {@link
307 * java.lang.SecurityManager}, it uses the group of {@link
308 * System#getSecurityManager}, else the group of the thread
309 * invoking this <tt>defaultThreadFactory</tt> method. Each new
310 * thread is created as a non-daemon thread with priority set to
311 * the smaller of <tt>Thread.NORM_PRIORITY</tt> and the maximum
312 * priority permitted in the thread group. New threads have names
313 * accessible via {@link Thread#getName} of
314 * <em>pool-N-thread-M</em>, where <em>N</em> is the sequence
315 * number of this factory, and <em>M</em> is the sequence number
316 * of the thread created by this factory.
317 * @return a thread factory
318 */
319 public static ThreadFactory defaultThreadFactory() {
320 return new DefaultThreadFactory();
321 }
322
323 /**
324 * Returns a thread factory used to create new threads that
325 * have the same permissions as the current thread.
326 * This factory creates threads with the same settings as {@link
327 * Executors#defaultThreadFactory}, additionally setting the
328 * AccessControlContext and contextClassLoader of new threads to
329 * be the same as the thread invoking this
330 * <tt>privilegedThreadFactory</tt> method. A new
331 * <tt>privilegedThreadFactory</tt> can be created within an
332 * {@link AccessController#doPrivileged} action setting the
333 * current thread's access control context to create threads with
334 * the selected permission settings holding within that action.
335 *
336 * <p> Note that while tasks running within such threads will have
337 * the same access control and class loader settings as the
338 * current thread, they need not have the same {@link
339 * java.lang.ThreadLocal} or {@link
340 * java.lang.InheritableThreadLocal} values. If necessary,
341 * particular values of thread locals can be set or reset before
342 * any task runs in {@link ThreadPoolExecutor} subclasses using
343 * {@link ThreadPoolExecutor#beforeExecute}. Also, if it is
344 * necessary to initialize worker threads to have the same
345 * InheritableThreadLocal settings as some other designated
346 * thread, you can create a custom ThreadFactory in which that
347 * thread waits for and services requests to create others that
348 * will inherit its values.
349 *
350 * @return a thread factory
351 * @throws AccessControlException if the current access control
352 * context does not have permission to both get and set context
353 * class loader.
354 */
355 public static ThreadFactory privilegedThreadFactory() {
356 return new PrivilegedThreadFactory();
357 }
358
359 /**
360 * Returns a {@link Callable} object that, when
361 * called, runs the given task and returns the given result. This
362 * can be useful when applying methods requiring a
363 * <tt>Callable</tt> to an otherwise resultless action.
364 * @param task the task to run
365 * @param result the result to return
366 * @return a callable object
367 * @throws NullPointerException if task null
368 */
369 public static <T> Callable<T> callable(Runnable task, T result) {
370 if (task == null)
371 throw new NullPointerException();
372 return new RunnableAdapter<T>(task, result);
373 }
374
375 /**
376 * Returns a {@link Callable} object that, when
377 * called, runs the given task and returns <tt>null</tt>.
378 * @param task the task to run
379 * @return a callable object
380 * @throws NullPointerException if task null
381 */
382 public static Callable<Object> callable(Runnable task) {
383 if (task == null)
384 throw new NullPointerException();
385 return new RunnableAdapter<Object>(task, null);
386 }
387
388 /**
389 * Returns a {@link Callable} object that, when
390 * called, runs the given privileged action and returns its result.
391 * @param action the privileged action to run
392 * @return a callable object
393 * @throws NullPointerException if action null
394 */
395 public static Callable<Object> callable(
396 final PrivilegedAction<?> action) {
397 if (action == null)
398 throw new NullPointerException();
399 return new Callable<Object>() {
400 public Object call() {
401 return action.run();
402 }
403 };
404 }
405
406 /**
407 * Returns a {@link Callable} object that, when
408 * called, runs the given privileged exception action and returns
409 * its result.
410 * @param action the privileged exception action to run
411 * @return a callable object
412 * @throws NullPointerException if action null
413 */
414 public static Callable<Object> callable(
415 final PrivilegedExceptionAction<?> action) {
416 if (action == null)
417 throw new NullPointerException();
418 return new Callable<Object>() {
419 public Object call() throws Exception {
420 return action.run();
421 }
422 };
423 }
424
425 /**
426 * Returns a {@link Callable} object that will, when
427 * called, execute the given <tt>callable</tt> under the current
428 * access control context. This method should normally be
429 * invoked within an {@link AccessController#doPrivileged} action
430 * to create callables that will, if possible, execute under the
431 * selected permission settings holding within that action; or if
432 * not possible, throw an associated {@link
433 * AccessControlException}.
434 * @param callable the underlying task
435 * @return a callable object
436 * @throws NullPointerException if callable null
437 *
438 */
439 public static <T> Callable<T> privilegedCallable(
440 Callable<T> callable) {
441 if (callable == null)
442 throw new NullPointerException();
443 return new PrivilegedCallable<T>(callable);
444 }
445
446 /**
447 * Returns a {@link Callable} object that will, when
448 * called, execute the given <tt>callable</tt> under the current
449 * access control context, with the current context class loader
450 * as the context class loader. This method should normally be
451 * invoked within an {@link AccessController#doPrivileged} action
452 * to create callables that will, if possible, execute under the
453 * selected permission settings holding within that action; or if
454 * not possible, throw an associated {@link
455 * AccessControlException}.
456 * @param callable the underlying task
457 *
458 * @return a callable object
459 * @throws NullPointerException if callable null
460 * @throws AccessControlException if the current access control
461 * context does not have permission to both set and get context
462 * class loader.
463 */
464 public static <T> Callable<T> privilegedCallableUsingCurrentClassLoader(
465 Callable<T> callable) {
466 if (callable == null)
467 throw new NullPointerException();
468 return new PrivilegedCallableUsingCurrentClassLoader<T>(
469 callable);
470 }
471
472 // Non-public classes supporting the public methods
473
474 /**
475 * A callable that runs given task and returns given result
476 */
477 static final class RunnableAdapter<T> implements Callable<T> {
478 final Runnable task;
479 final T result;
480
481 RunnableAdapter(Runnable task, T result) {
482 this .task = task;
483 this .result = result;
484 }
485
486 public T call() {
487 task.run();
488 return result;
489 }
490 }
491
492 /**
493 * A callable that runs under established access control settings
494 */
495 static final class PrivilegedCallable<T> implements Callable<T> {
496 private final Callable<T> task;
497 private final AccessControlContext acc;
498
499 PrivilegedCallable(Callable<T> task) {
500 this .task = task;
501 this .acc = AccessController.getContext();
502 }
503
504 public T call() throws Exception {
505 try {
506 return AccessController.doPrivileged(
507 new PrivilegedExceptionAction<T>() {
508 public T run() throws Exception {
509 return task.call();
510 }
511 }, acc);
512 } catch (PrivilegedActionException e) {
513 throw e.getException();
514 }
515 }
516 }
517
518 /**
519 * A callable that runs under established access control settings and
520 * current ClassLoader
521 */
522 static final class PrivilegedCallableUsingCurrentClassLoader<T>
523 implements Callable<T> {
524 private final Callable<T> task;
525 private final AccessControlContext acc;
526 private final ClassLoader ccl;
527
528 PrivilegedCallableUsingCurrentClassLoader(Callable<T> task) {
529 SecurityManager sm = System.getSecurityManager();
530 if (sm != null) {
531 // Calls to getContextClassLoader from this class
532 // never trigger a security check, but we check
533 // whether our callers have this permission anyways.
534 sm
535 .checkPermission(SecurityConstants.GET_CLASSLOADER_PERMISSION);
536
537 // Whether setContextClassLoader turns out to be necessary
538 // or not, we fail fast if permission is not available.
539 sm.checkPermission(new RuntimePermission(
540 "setContextClassLoader"));
541 }
542 this .task = task;
543 this .acc = AccessController.getContext();
544 this .ccl = Thread.currentThread().getContextClassLoader();
545 }
546
547 public T call() throws Exception {
548 try {
549 return AccessController.doPrivileged(
550 new PrivilegedExceptionAction<T>() {
551 public T run() throws Exception {
552 ClassLoader savedcl = null;
553 Thread t = Thread.currentThread();
554 try {
555 ClassLoader cl = t
556 .getContextClassLoader();
557 if (ccl != cl) {
558 t.setContextClassLoader(ccl);
559 savedcl = cl;
560 }
561 return task.call();
562 } finally {
563 if (savedcl != null)
564 t
565 .setContextClassLoader(savedcl);
566 }
567 }
568 }, acc);
569 } catch (PrivilegedActionException e) {
570 throw e.getException();
571 }
572 }
573 }
574
575 /**
576 * The default thread factory
577 */
578 static class DefaultThreadFactory implements ThreadFactory {
579 private static final AtomicInteger poolNumber = new AtomicInteger(
580 1);
581 private final ThreadGroup group;
582 private final AtomicInteger threadNumber = new AtomicInteger(1);
583 private final String namePrefix;
584
585 DefaultThreadFactory() {
586 SecurityManager s = System.getSecurityManager();
587 group = (s != null) ? s.getThreadGroup() : Thread
588 .currentThread().getThreadGroup();
589 namePrefix = "pool-" + poolNumber.getAndIncrement()
590 + "-thread-";
591 }
592
593 public Thread newThread(Runnable r) {
594 Thread t = new Thread(group, r, namePrefix
595 + threadNumber.getAndIncrement(), 0);
596 if (t.isDaemon())
597 t.setDaemon(false);
598 if (t.getPriority() != Thread.NORM_PRIORITY)
599 t.setPriority(Thread.NORM_PRIORITY);
600 return t;
601 }
602 }
603
604 /**
605 * Thread factory capturing access control context and class loader
606 */
607 static class PrivilegedThreadFactory extends DefaultThreadFactory {
608 private final AccessControlContext acc;
609 private final ClassLoader ccl;
610
611 PrivilegedThreadFactory() {
612 super ();
613 SecurityManager sm = System.getSecurityManager();
614 if (sm != null) {
615 // Calls to getContextClassLoader from this class
616 // never trigger a security check, but we check
617 // whether our callers have this permission anyways.
618 sm
619 .checkPermission(SecurityConstants.GET_CLASSLOADER_PERMISSION);
620
621 // Fail fast
622 sm.checkPermission(new RuntimePermission(
623 "setContextClassLoader"));
624 }
625 this .acc = AccessController.getContext();
626 this .ccl = Thread.currentThread().getContextClassLoader();
627 }
628
629 public Thread newThread(final Runnable r) {
630 return super .newThread(new Runnable() {
631 public void run() {
632 AccessController.doPrivileged(
633 new PrivilegedAction<Void>() {
634 public Void run() {
635 Thread.currentThread()
636 .setContextClassLoader(ccl);
637 r.run();
638 return null;
639 }
640 }, acc);
641 }
642 });
643 }
644 }
645
646 /**
647 * A wrapper class that exposes only the ExecutorService methods
648 * of an ExecutorService implementation.
649 */
650 static class DelegatedExecutorService extends
651 AbstractExecutorService {
652 private final ExecutorService e;
653
654 DelegatedExecutorService(ExecutorService executor) {
655 e = executor;
656 }
657
658 public void execute(Runnable command) {
659 e.execute(command);
660 }
661
662 public void shutdown() {
663 e.shutdown();
664 }
665
666 public List<Runnable> shutdownNow() {
667 return e.shutdownNow();
668 }
669
670 public boolean isShutdown() {
671 return e.isShutdown();
672 }
673
674 public boolean isTerminated() {
675 return e.isTerminated();
676 }
677
678 public boolean awaitTermination(long timeout, TimeUnit unit)
679 throws InterruptedException {
680 return e.awaitTermination(timeout, unit);
681 }
682
683 public Future<?> submit(Runnable task) {
684 return e.submit(task);
685 }
686
687 public <T> Future<T> submit(Callable<T> task) {
688 return e.submit(task);
689 }
690
691 public <T> Future<T> submit(Runnable task, T result) {
692 return e.submit(task, result);
693 }
694
695 public <T> List<Future<T>> invokeAll(
696 Collection<? extends Callable<T>> tasks)
697 throws InterruptedException {
698 return e.invokeAll(tasks);
699 }
700
701 public <T> List<Future<T>> invokeAll(
702 Collection<? extends Callable<T>> tasks, long timeout,
703 TimeUnit unit) throws InterruptedException {
704 return e.invokeAll(tasks, timeout, unit);
705 }
706
707 public <T> T invokeAny(Collection<? extends Callable<T>> tasks)
708 throws InterruptedException, ExecutionException {
709 return e.invokeAny(tasks);
710 }
711
712 public <T> T invokeAny(Collection<? extends Callable<T>> tasks,
713 long timeout, TimeUnit unit)
714 throws InterruptedException, ExecutionException,
715 TimeoutException {
716 return e.invokeAny(tasks, timeout, unit);
717 }
718 }
719
720 static class FinalizableDelegatedExecutorService extends
721 DelegatedExecutorService {
722 FinalizableDelegatedExecutorService(ExecutorService executor) {
723 super (executor);
724 }
725
726 protected void finalize() {
727 super .shutdown();
728 }
729 }
730
731 /**
732 * A wrapper class that exposes only the ScheduledExecutorService
733 * methods of a ScheduledExecutorService implementation.
734 */
735 static class DelegatedScheduledExecutorService extends
736 DelegatedExecutorService implements
737 ScheduledExecutorService {
738 private final ScheduledExecutorService e;
739
740 DelegatedScheduledExecutorService(
741 ScheduledExecutorService executor) {
742 super (executor);
743 e = executor;
744 }
745
746 public ScheduledFuture<?> schedule(Runnable command,
747 long delay, TimeUnit unit) {
748 return e.schedule(command, delay, unit);
749 }
750
751 public <V> ScheduledFuture<V> schedule(Callable<V> callable,
752 long delay, TimeUnit unit) {
753 return e.schedule(callable, delay, unit);
754 }
755
756 public ScheduledFuture<?> scheduleAtFixedRate(Runnable command,
757 long initialDelay, long period, TimeUnit unit) {
758 return e.scheduleAtFixedRate(command, initialDelay, period,
759 unit);
760 }
761
762 public ScheduledFuture<?> scheduleWithFixedDelay(
763 Runnable command, long initialDelay, long delay,
764 TimeUnit unit) {
765 return e.scheduleWithFixedDelay(command, initialDelay,
766 delay, unit);
767 }
768 }
769
770 /** Cannot instantiate. */
771 private Executors() {
772 }
773 }
|