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