jaroslav@1890: /* jaroslav@1890: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. jaroslav@1890: * jaroslav@1890: * This code is free software; you can redistribute it and/or modify it jaroslav@1890: * under the terms of the GNU General Public License version 2 only, as jaroslav@1890: * published by the Free Software Foundation. Oracle designates this jaroslav@1890: * particular file as subject to the "Classpath" exception as provided jaroslav@1890: * by Oracle in the LICENSE file that accompanied this code. jaroslav@1890: * jaroslav@1890: * This code is distributed in the hope that it will be useful, but WITHOUT jaroslav@1890: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or jaroslav@1890: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License jaroslav@1890: * version 2 for more details (a copy is included in the LICENSE file that jaroslav@1890: * accompanied this code). jaroslav@1890: * jaroslav@1890: * You should have received a copy of the GNU General Public License version jaroslav@1890: * 2 along with this work; if not, write to the Free Software Foundation, jaroslav@1890: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. jaroslav@1890: * jaroslav@1890: * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA jaroslav@1890: * or visit www.oracle.com if you need additional information or have any jaroslav@1890: * questions. jaroslav@1890: */ jaroslav@1890: jaroslav@1890: /* jaroslav@1890: * This file is available under and governed by the GNU General Public jaroslav@1890: * License version 2 only, as published by the Free Software Foundation. jaroslav@1890: * However, the following notice accompanied the original version of this jaroslav@1890: * file: jaroslav@1890: * jaroslav@1890: * Written by Doug Lea with assistance from members of JCP JSR-166 jaroslav@1890: * Expert Group and released to the public domain, as explained at jaroslav@1890: * http://creativecommons.org/publicdomain/zero/1.0/ jaroslav@1890: */ jaroslav@1890: jaroslav@1890: package java.util.concurrent; jaroslav@1890: import java.util.*; jaroslav@1890: import java.util.concurrent.atomic.AtomicInteger; jaroslav@1890: import java.security.AccessControlContext; jaroslav@1890: import java.security.AccessController; jaroslav@1890: import java.security.PrivilegedAction; jaroslav@1890: import java.security.PrivilegedExceptionAction; jaroslav@1890: import java.security.PrivilegedActionException; jaroslav@1890: import java.security.AccessControlException; jaroslav@1890: import sun.security.util.SecurityConstants; jaroslav@1890: jaroslav@1890: /** jaroslav@1890: * Factory and utility methods for {@link Executor}, {@link jaroslav@1890: * ExecutorService}, {@link ScheduledExecutorService}, {@link jaroslav@1890: * ThreadFactory}, and {@link Callable} classes defined in this jaroslav@1890: * package. This class supports the following kinds of methods: jaroslav@1890: * jaroslav@1890: * jaroslav@1890: * jaroslav@1890: * @since 1.5 jaroslav@1890: * @author Doug Lea jaroslav@1890: */ jaroslav@1890: public class Executors { jaroslav@1890: jaroslav@1890: /** jaroslav@1890: * Creates a thread pool that reuses a fixed number of threads jaroslav@1890: * operating off a shared unbounded queue. At any point, at most jaroslav@1890: * nThreads threads will be active processing tasks. jaroslav@1890: * If additional tasks are submitted when all threads are active, jaroslav@1890: * they will wait in the queue until a thread is available. jaroslav@1890: * If any thread terminates due to a failure during execution jaroslav@1890: * prior to shutdown, a new one will take its place if needed to jaroslav@1890: * execute subsequent tasks. The threads in the pool will exist jaroslav@1890: * until it is explicitly {@link ExecutorService#shutdown shutdown}. jaroslav@1890: * jaroslav@1890: * @param nThreads the number of threads in the pool jaroslav@1890: * @return the newly created thread pool jaroslav@1890: * @throws IllegalArgumentException if {@code nThreads <= 0} jaroslav@1890: */ jaroslav@1890: public static ExecutorService newFixedThreadPool(int nThreads) { jaroslav@1890: return new ThreadPoolExecutor(nThreads, nThreads, jaroslav@1890: 0L, TimeUnit.MILLISECONDS, jaroslav@1890: new LinkedBlockingQueue()); jaroslav@1890: } jaroslav@1890: jaroslav@1890: /** jaroslav@1890: * Creates a thread pool that reuses a fixed number of threads jaroslav@1890: * operating off a shared unbounded queue, using the provided jaroslav@1890: * ThreadFactory to create new threads when needed. At any point, jaroslav@1890: * at most nThreads threads will be active processing jaroslav@1890: * tasks. If additional tasks are submitted when all threads are jaroslav@1890: * active, they will wait in the queue until a thread is jaroslav@1890: * available. If any thread terminates due to a failure during jaroslav@1890: * execution prior to shutdown, a new one will take its place if jaroslav@1890: * needed to execute subsequent tasks. The threads in the pool will jaroslav@1890: * exist until it is explicitly {@link ExecutorService#shutdown jaroslav@1890: * shutdown}. jaroslav@1890: * jaroslav@1890: * @param nThreads the number of threads in the pool jaroslav@1890: * @param threadFactory the factory to use when creating new threads jaroslav@1890: * @return the newly created thread pool jaroslav@1890: * @throws NullPointerException if threadFactory is null jaroslav@1890: * @throws IllegalArgumentException if {@code nThreads <= 0} jaroslav@1890: */ jaroslav@1890: public static ExecutorService newFixedThreadPool(int nThreads, ThreadFactory threadFactory) { jaroslav@1890: return new ThreadPoolExecutor(nThreads, nThreads, jaroslav@1890: 0L, TimeUnit.MILLISECONDS, jaroslav@1890: new LinkedBlockingQueue(), jaroslav@1890: threadFactory); jaroslav@1890: } jaroslav@1890: jaroslav@1890: /** jaroslav@1890: * Creates an Executor that uses a single worker thread operating jaroslav@1890: * off an unbounded queue. (Note however that if this single jaroslav@1890: * thread terminates due to a failure during execution prior to jaroslav@1890: * shutdown, a new one will take its place if needed to execute jaroslav@1890: * subsequent tasks.) Tasks are guaranteed to execute jaroslav@1890: * sequentially, and no more than one task will be active at any jaroslav@1890: * given time. Unlike the otherwise equivalent jaroslav@1890: * newFixedThreadPool(1) the returned executor is jaroslav@1890: * guaranteed not to be reconfigurable to use additional threads. jaroslav@1890: * jaroslav@1890: * @return the newly created single-threaded Executor jaroslav@1890: */ jaroslav@1890: public static ExecutorService newSingleThreadExecutor() { jaroslav@1890: return new FinalizableDelegatedExecutorService jaroslav@1890: (new ThreadPoolExecutor(1, 1, jaroslav@1890: 0L, TimeUnit.MILLISECONDS, jaroslav@1890: new LinkedBlockingQueue())); jaroslav@1890: } jaroslav@1890: jaroslav@1890: /** jaroslav@1890: * Creates an Executor that uses a single worker thread operating jaroslav@1890: * off an unbounded queue, and uses the provided ThreadFactory to jaroslav@1890: * create a new thread when needed. Unlike the otherwise jaroslav@1890: * equivalent newFixedThreadPool(1, threadFactory) the jaroslav@1890: * returned executor is guaranteed not to be reconfigurable to use jaroslav@1890: * additional threads. jaroslav@1890: * jaroslav@1890: * @param threadFactory the factory to use when creating new jaroslav@1890: * threads jaroslav@1890: * jaroslav@1890: * @return the newly created single-threaded Executor jaroslav@1890: * @throws NullPointerException if threadFactory is null jaroslav@1890: */ jaroslav@1890: public static ExecutorService newSingleThreadExecutor(ThreadFactory threadFactory) { jaroslav@1890: return new FinalizableDelegatedExecutorService jaroslav@1890: (new ThreadPoolExecutor(1, 1, jaroslav@1890: 0L, TimeUnit.MILLISECONDS, jaroslav@1890: new LinkedBlockingQueue(), jaroslav@1890: threadFactory)); jaroslav@1890: } jaroslav@1890: jaroslav@1890: /** jaroslav@1890: * Creates a thread pool that creates new threads as needed, but jaroslav@1890: * will reuse previously constructed threads when they are jaroslav@1890: * available. These pools will typically improve the performance jaroslav@1890: * of programs that execute many short-lived asynchronous tasks. jaroslav@1890: * Calls to execute will reuse previously constructed jaroslav@1890: * threads if available. If no existing thread is available, a new jaroslav@1890: * thread will be created and added to the pool. Threads that have jaroslav@1890: * not been used for sixty seconds are terminated and removed from jaroslav@1890: * the cache. Thus, a pool that remains idle for long enough will jaroslav@1890: * not consume any resources. Note that pools with similar jaroslav@1890: * properties but different details (for example, timeout parameters) jaroslav@1890: * may be created using {@link ThreadPoolExecutor} constructors. jaroslav@1890: * jaroslav@1890: * @return the newly created thread pool jaroslav@1890: */ jaroslav@1890: public static ExecutorService newCachedThreadPool() { jaroslav@1890: return new ThreadPoolExecutor(0, Integer.MAX_VALUE, jaroslav@1890: 60L, TimeUnit.SECONDS, jaroslav@1890: new SynchronousQueue()); jaroslav@1890: } jaroslav@1890: jaroslav@1890: /** jaroslav@1890: * Creates a thread pool that creates new threads as needed, but jaroslav@1890: * will reuse previously constructed threads when they are jaroslav@1890: * available, and uses the provided jaroslav@1890: * ThreadFactory to create new threads when needed. jaroslav@1890: * @param threadFactory the factory to use when creating new threads jaroslav@1890: * @return the newly created thread pool jaroslav@1890: * @throws NullPointerException if threadFactory is null jaroslav@1890: */ jaroslav@1890: public static ExecutorService newCachedThreadPool(ThreadFactory threadFactory) { jaroslav@1890: return new ThreadPoolExecutor(0, Integer.MAX_VALUE, jaroslav@1890: 60L, TimeUnit.SECONDS, jaroslav@1890: new SynchronousQueue(), jaroslav@1890: threadFactory); jaroslav@1890: } jaroslav@1890: jaroslav@1890: /** jaroslav@1890: * Creates a single-threaded executor that can schedule commands jaroslav@1890: * to run after a given delay, or to execute periodically. jaroslav@1890: * (Note however that if this single jaroslav@1890: * thread terminates due to a failure during execution prior to jaroslav@1890: * shutdown, a new one will take its place if needed to execute jaroslav@1890: * subsequent tasks.) Tasks are guaranteed to execute jaroslav@1890: * sequentially, and no more than one task will be active at any jaroslav@1890: * given time. Unlike the otherwise equivalent jaroslav@1890: * newScheduledThreadPool(1) the returned executor is jaroslav@1890: * guaranteed not to be reconfigurable to use additional threads. jaroslav@1890: * @return the newly created scheduled executor jaroslav@1890: */ jaroslav@1890: public static ScheduledExecutorService newSingleThreadScheduledExecutor() { jaroslav@1890: return new DelegatedScheduledExecutorService jaroslav@1890: (new ScheduledThreadPoolExecutor(1)); jaroslav@1890: } jaroslav@1890: jaroslav@1890: /** jaroslav@1890: * Creates a single-threaded executor that can schedule commands jaroslav@1890: * to run after a given delay, or to execute periodically. (Note jaroslav@1890: * however that if this single thread terminates due to a failure jaroslav@1890: * during execution prior to shutdown, a new one will take its jaroslav@1890: * place if needed to execute subsequent tasks.) Tasks are jaroslav@1890: * guaranteed to execute sequentially, and no more than one task jaroslav@1890: * will be active at any given time. Unlike the otherwise jaroslav@1890: * equivalent newScheduledThreadPool(1, threadFactory) jaroslav@1890: * the returned executor is guaranteed not to be reconfigurable to jaroslav@1890: * use additional threads. jaroslav@1890: * @param threadFactory the factory to use when creating new jaroslav@1890: * threads jaroslav@1890: * @return a newly created scheduled executor jaroslav@1890: * @throws NullPointerException if threadFactory is null jaroslav@1890: */ jaroslav@1890: public static ScheduledExecutorService newSingleThreadScheduledExecutor(ThreadFactory threadFactory) { jaroslav@1890: return new DelegatedScheduledExecutorService jaroslav@1890: (new ScheduledThreadPoolExecutor(1, threadFactory)); jaroslav@1890: } jaroslav@1890: jaroslav@1890: /** jaroslav@1890: * Creates a thread pool that can schedule commands to run after a jaroslav@1890: * given delay, or to execute periodically. jaroslav@1890: * @param corePoolSize the number of threads to keep in the pool, jaroslav@1890: * even if they are idle. jaroslav@1890: * @return a newly created scheduled thread pool jaroslav@1890: * @throws IllegalArgumentException if {@code corePoolSize < 0} jaroslav@1890: */ jaroslav@1890: public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) { jaroslav@1890: return new ScheduledThreadPoolExecutor(corePoolSize); jaroslav@1890: } jaroslav@1890: jaroslav@1890: /** jaroslav@1890: * Creates a thread pool that can schedule commands to run after a jaroslav@1890: * given delay, or to execute periodically. jaroslav@1890: * @param corePoolSize the number of threads to keep in the pool, jaroslav@1890: * even if they are idle. jaroslav@1890: * @param threadFactory the factory to use when the executor jaroslav@1890: * creates a new thread. jaroslav@1890: * @return a newly created scheduled thread pool jaroslav@1890: * @throws IllegalArgumentException if {@code corePoolSize < 0} jaroslav@1890: * @throws NullPointerException if threadFactory is null jaroslav@1890: */ jaroslav@1890: public static ScheduledExecutorService newScheduledThreadPool( jaroslav@1890: int corePoolSize, ThreadFactory threadFactory) { jaroslav@1890: return new ScheduledThreadPoolExecutor(corePoolSize, threadFactory); jaroslav@1890: } jaroslav@1890: jaroslav@1890: jaroslav@1890: /** jaroslav@1890: * Returns an object that delegates all defined {@link jaroslav@1890: * ExecutorService} methods to the given executor, but not any jaroslav@1890: * other methods that might otherwise be accessible using jaroslav@1890: * casts. This provides a way to safely "freeze" configuration and jaroslav@1890: * disallow tuning of a given concrete implementation. jaroslav@1890: * @param executor the underlying implementation jaroslav@1890: * @return an ExecutorService instance jaroslav@1890: * @throws NullPointerException if executor null jaroslav@1890: */ jaroslav@1890: public static ExecutorService unconfigurableExecutorService(ExecutorService executor) { jaroslav@1890: if (executor == null) jaroslav@1890: throw new NullPointerException(); jaroslav@1890: return new DelegatedExecutorService(executor); jaroslav@1890: } jaroslav@1890: jaroslav@1890: /** jaroslav@1890: * Returns an object that delegates all defined {@link jaroslav@1890: * ScheduledExecutorService} methods to the given executor, but jaroslav@1890: * not any other methods that might otherwise be accessible using jaroslav@1890: * casts. This provides a way to safely "freeze" configuration and jaroslav@1890: * disallow tuning of a given concrete implementation. jaroslav@1890: * @param executor the underlying implementation jaroslav@1890: * @return a ScheduledExecutorService instance jaroslav@1890: * @throws NullPointerException if executor null jaroslav@1890: */ jaroslav@1890: public static ScheduledExecutorService unconfigurableScheduledExecutorService(ScheduledExecutorService executor) { jaroslav@1890: if (executor == null) jaroslav@1890: throw new NullPointerException(); jaroslav@1890: return new DelegatedScheduledExecutorService(executor); jaroslav@1890: } jaroslav@1890: jaroslav@1890: /** jaroslav@1890: * Returns a default thread factory used to create new threads. jaroslav@1890: * This factory creates all new threads used by an Executor in the jaroslav@1890: * same {@link ThreadGroup}. If there is a {@link jaroslav@1890: * java.lang.SecurityManager}, it uses the group of {@link jaroslav@1890: * System#getSecurityManager}, else the group of the thread jaroslav@1890: * invoking this defaultThreadFactory method. Each new jaroslav@1890: * thread is created as a non-daemon thread with priority set to jaroslav@1890: * the smaller of Thread.NORM_PRIORITY and the maximum jaroslav@1890: * priority permitted in the thread group. New threads have names jaroslav@1890: * accessible via {@link Thread#getName} of jaroslav@1890: * pool-N-thread-M, where N is the sequence jaroslav@1890: * number of this factory, and M is the sequence number jaroslav@1890: * of the thread created by this factory. jaroslav@1890: * @return a thread factory jaroslav@1890: */ jaroslav@1890: public static ThreadFactory defaultThreadFactory() { jaroslav@1890: return new DefaultThreadFactory(); jaroslav@1890: } jaroslav@1890: jaroslav@1890: /** jaroslav@1890: * Returns a thread factory used to create new threads that jaroslav@1890: * have the same permissions as the current thread. jaroslav@1890: * This factory creates threads with the same settings as {@link jaroslav@1890: * Executors#defaultThreadFactory}, additionally setting the jaroslav@1890: * AccessControlContext and contextClassLoader of new threads to jaroslav@1890: * be the same as the thread invoking this jaroslav@1890: * privilegedThreadFactory method. A new jaroslav@1890: * privilegedThreadFactory can be created within an jaroslav@1890: * {@link AccessController#doPrivileged} action setting the jaroslav@1890: * current thread's access control context to create threads with jaroslav@1890: * the selected permission settings holding within that action. jaroslav@1890: * jaroslav@1890: *

Note that while tasks running within such threads will have jaroslav@1890: * the same access control and class loader settings as the jaroslav@1890: * current thread, they need not have the same {@link jaroslav@1890: * java.lang.ThreadLocal} or {@link jaroslav@1890: * java.lang.InheritableThreadLocal} values. If necessary, jaroslav@1890: * particular values of thread locals can be set or reset before jaroslav@1890: * any task runs in {@link ThreadPoolExecutor} subclasses using jaroslav@1890: * {@link ThreadPoolExecutor#beforeExecute}. Also, if it is jaroslav@1890: * necessary to initialize worker threads to have the same jaroslav@1890: * InheritableThreadLocal settings as some other designated jaroslav@1890: * thread, you can create a custom ThreadFactory in which that jaroslav@1890: * thread waits for and services requests to create others that jaroslav@1890: * will inherit its values. jaroslav@1890: * jaroslav@1890: * @return a thread factory jaroslav@1890: * @throws AccessControlException if the current access control jaroslav@1890: * context does not have permission to both get and set context jaroslav@1890: * class loader. jaroslav@1890: */ jaroslav@1890: public static ThreadFactory privilegedThreadFactory() { jaroslav@1890: return new PrivilegedThreadFactory(); jaroslav@1890: } jaroslav@1890: jaroslav@1890: /** jaroslav@1890: * Returns a {@link Callable} object that, when jaroslav@1890: * called, runs the given task and returns the given result. This jaroslav@1890: * can be useful when applying methods requiring a jaroslav@1890: * Callable to an otherwise resultless action. jaroslav@1890: * @param task the task to run jaroslav@1890: * @param result the result to return jaroslav@1890: * @return a callable object jaroslav@1890: * @throws NullPointerException if task null jaroslav@1890: */ jaroslav@1890: public static Callable callable(Runnable task, T result) { jaroslav@1890: if (task == null) jaroslav@1890: throw new NullPointerException(); jaroslav@1890: return new RunnableAdapter(task, result); jaroslav@1890: } jaroslav@1890: jaroslav@1890: /** jaroslav@1890: * Returns a {@link Callable} object that, when jaroslav@1890: * called, runs the given task and returns null. jaroslav@1890: * @param task the task to run jaroslav@1890: * @return a callable object jaroslav@1890: * @throws NullPointerException if task null jaroslav@1890: */ jaroslav@1890: public static Callable callable(Runnable task) { jaroslav@1890: if (task == null) jaroslav@1890: throw new NullPointerException(); jaroslav@1890: return new RunnableAdapter(task, null); jaroslav@1890: } jaroslav@1890: jaroslav@1890: /** jaroslav@1890: * Returns a {@link Callable} object that, when jaroslav@1890: * called, runs the given privileged action and returns its result. jaroslav@1890: * @param action the privileged action to run jaroslav@1890: * @return a callable object jaroslav@1890: * @throws NullPointerException if action null jaroslav@1890: */ jaroslav@1890: public static Callable callable(final PrivilegedAction action) { jaroslav@1890: if (action == null) jaroslav@1890: throw new NullPointerException(); jaroslav@1890: return new Callable() { jaroslav@1890: public Object call() { return action.run(); }}; jaroslav@1890: } jaroslav@1890: jaroslav@1890: /** jaroslav@1890: * Returns a {@link Callable} object that, when jaroslav@1890: * called, runs the given privileged exception action and returns jaroslav@1890: * its result. jaroslav@1890: * @param action the privileged exception action to run jaroslav@1890: * @return a callable object jaroslav@1890: * @throws NullPointerException if action null jaroslav@1890: */ jaroslav@1890: public static Callable callable(final PrivilegedExceptionAction action) { jaroslav@1890: if (action == null) jaroslav@1890: throw new NullPointerException(); jaroslav@1890: return new Callable() { jaroslav@1890: public Object call() throws Exception { return action.run(); }}; jaroslav@1890: } jaroslav@1890: jaroslav@1890: /** jaroslav@1890: * Returns a {@link Callable} object that will, when jaroslav@1890: * called, execute the given callable under the current jaroslav@1890: * access control context. This method should normally be jaroslav@1890: * invoked within an {@link AccessController#doPrivileged} action jaroslav@1890: * to create callables that will, if possible, execute under the jaroslav@1890: * selected permission settings holding within that action; or if jaroslav@1890: * not possible, throw an associated {@link jaroslav@1890: * AccessControlException}. jaroslav@1890: * @param callable the underlying task jaroslav@1890: * @return a callable object jaroslav@1890: * @throws NullPointerException if callable null jaroslav@1890: * jaroslav@1890: */ jaroslav@1890: public static Callable privilegedCallable(Callable callable) { jaroslav@1890: if (callable == null) jaroslav@1890: throw new NullPointerException(); jaroslav@1890: return new PrivilegedCallable(callable); jaroslav@1890: } jaroslav@1890: jaroslav@1890: /** jaroslav@1890: * Returns a {@link Callable} object that will, when jaroslav@1890: * called, execute the given callable under the current jaroslav@1890: * access control context, with the current context class loader jaroslav@1890: * as the context class loader. This method should normally be jaroslav@1890: * invoked within an {@link AccessController#doPrivileged} action jaroslav@1890: * to create callables that will, if possible, execute under the jaroslav@1890: * selected permission settings holding within that action; or if jaroslav@1890: * not possible, throw an associated {@link jaroslav@1890: * AccessControlException}. jaroslav@1890: * @param callable the underlying task jaroslav@1890: * jaroslav@1890: * @return a callable object jaroslav@1890: * @throws NullPointerException if callable null jaroslav@1890: * @throws AccessControlException if the current access control jaroslav@1890: * context does not have permission to both set and get context jaroslav@1890: * class loader. jaroslav@1890: */ jaroslav@1890: public static Callable privilegedCallableUsingCurrentClassLoader(Callable callable) { jaroslav@1890: if (callable == null) jaroslav@1890: throw new NullPointerException(); jaroslav@1890: return new PrivilegedCallableUsingCurrentClassLoader(callable); jaroslav@1890: } jaroslav@1890: jaroslav@1890: // Non-public classes supporting the public methods jaroslav@1890: jaroslav@1890: /** jaroslav@1890: * A callable that runs given task and returns given result jaroslav@1890: */ jaroslav@1890: static final class RunnableAdapter implements Callable { jaroslav@1890: final Runnable task; jaroslav@1890: final T result; jaroslav@1890: RunnableAdapter(Runnable task, T result) { jaroslav@1890: this.task = task; jaroslav@1890: this.result = result; jaroslav@1890: } jaroslav@1890: public T call() { jaroslav@1890: task.run(); jaroslav@1890: return result; jaroslav@1890: } jaroslav@1890: } jaroslav@1890: jaroslav@1890: /** jaroslav@1890: * A callable that runs under established access control settings jaroslav@1890: */ jaroslav@1890: static final class PrivilegedCallable implements Callable { jaroslav@1890: private final Callable task; jaroslav@1890: private final AccessControlContext acc; jaroslav@1890: jaroslav@1890: PrivilegedCallable(Callable task) { jaroslav@1890: this.task = task; jaroslav@1890: this.acc = AccessController.getContext(); jaroslav@1890: } jaroslav@1890: jaroslav@1890: public T call() throws Exception { jaroslav@1890: try { jaroslav@1890: return AccessController.doPrivileged( jaroslav@1890: new PrivilegedExceptionAction() { jaroslav@1890: public T run() throws Exception { jaroslav@1890: return task.call(); jaroslav@1890: } jaroslav@1890: }, acc); jaroslav@1890: } catch (PrivilegedActionException e) { jaroslav@1890: throw e.getException(); jaroslav@1890: } jaroslav@1890: } jaroslav@1890: } jaroslav@1890: jaroslav@1890: /** jaroslav@1890: * A callable that runs under established access control settings and jaroslav@1890: * current ClassLoader jaroslav@1890: */ jaroslav@1890: static final class PrivilegedCallableUsingCurrentClassLoader implements Callable { jaroslav@1890: private final Callable task; jaroslav@1890: private final AccessControlContext acc; jaroslav@1890: private final ClassLoader ccl; jaroslav@1890: jaroslav@1890: PrivilegedCallableUsingCurrentClassLoader(Callable task) { jaroslav@1890: SecurityManager sm = System.getSecurityManager(); jaroslav@1890: if (sm != null) { jaroslav@1890: // Calls to getContextClassLoader from this class jaroslav@1890: // never trigger a security check, but we check jaroslav@1890: // whether our callers have this permission anyways. jaroslav@1890: sm.checkPermission(SecurityConstants.GET_CLASSLOADER_PERMISSION); jaroslav@1890: jaroslav@1890: // Whether setContextClassLoader turns out to be necessary jaroslav@1890: // or not, we fail fast if permission is not available. jaroslav@1890: sm.checkPermission(new RuntimePermission("setContextClassLoader")); jaroslav@1890: } jaroslav@1890: this.task = task; jaroslav@1890: this.acc = AccessController.getContext(); jaroslav@1890: this.ccl = Thread.currentThread().getContextClassLoader(); jaroslav@1890: } jaroslav@1890: jaroslav@1890: public T call() throws Exception { jaroslav@1890: try { jaroslav@1890: return AccessController.doPrivileged( jaroslav@1890: new PrivilegedExceptionAction() { jaroslav@1890: public T run() throws Exception { jaroslav@1890: ClassLoader savedcl = null; jaroslav@1890: Thread t = Thread.currentThread(); jaroslav@1890: try { jaroslav@1890: ClassLoader cl = t.getContextClassLoader(); jaroslav@1890: if (ccl != cl) { jaroslav@1890: t.setContextClassLoader(ccl); jaroslav@1890: savedcl = cl; jaroslav@1890: } jaroslav@1890: return task.call(); jaroslav@1890: } finally { jaroslav@1890: if (savedcl != null) jaroslav@1890: t.setContextClassLoader(savedcl); jaroslav@1890: } jaroslav@1890: } jaroslav@1890: }, acc); jaroslav@1890: } catch (PrivilegedActionException e) { jaroslav@1890: throw e.getException(); jaroslav@1890: } jaroslav@1890: } jaroslav@1890: } jaroslav@1890: jaroslav@1890: /** jaroslav@1890: * The default thread factory jaroslav@1890: */ jaroslav@1890: static class DefaultThreadFactory implements ThreadFactory { jaroslav@1890: private static final AtomicInteger poolNumber = new AtomicInteger(1); jaroslav@1890: private final ThreadGroup group; jaroslav@1890: private final AtomicInteger threadNumber = new AtomicInteger(1); jaroslav@1890: private final String namePrefix; jaroslav@1890: jaroslav@1890: DefaultThreadFactory() { jaroslav@1890: SecurityManager s = System.getSecurityManager(); jaroslav@1890: group = (s != null) ? s.getThreadGroup() : jaroslav@1890: Thread.currentThread().getThreadGroup(); jaroslav@1890: namePrefix = "pool-" + jaroslav@1890: poolNumber.getAndIncrement() + jaroslav@1890: "-thread-"; jaroslav@1890: } jaroslav@1890: jaroslav@1890: public Thread newThread(Runnable r) { jaroslav@1890: Thread t = new Thread(group, r, jaroslav@1890: namePrefix + threadNumber.getAndIncrement(), jaroslav@1890: 0); jaroslav@1890: if (t.isDaemon()) jaroslav@1890: t.setDaemon(false); jaroslav@1890: if (t.getPriority() != Thread.NORM_PRIORITY) jaroslav@1890: t.setPriority(Thread.NORM_PRIORITY); jaroslav@1890: return t; jaroslav@1890: } jaroslav@1890: } jaroslav@1890: jaroslav@1890: /** jaroslav@1890: * Thread factory capturing access control context and class loader jaroslav@1890: */ jaroslav@1890: static class PrivilegedThreadFactory extends DefaultThreadFactory { jaroslav@1890: private final AccessControlContext acc; jaroslav@1890: private final ClassLoader ccl; jaroslav@1890: jaroslav@1890: PrivilegedThreadFactory() { jaroslav@1890: super(); jaroslav@1890: SecurityManager sm = System.getSecurityManager(); jaroslav@1890: if (sm != null) { jaroslav@1890: // Calls to getContextClassLoader from this class jaroslav@1890: // never trigger a security check, but we check jaroslav@1890: // whether our callers have this permission anyways. jaroslav@1890: sm.checkPermission(SecurityConstants.GET_CLASSLOADER_PERMISSION); jaroslav@1890: jaroslav@1890: // Fail fast jaroslav@1890: sm.checkPermission(new RuntimePermission("setContextClassLoader")); jaroslav@1890: } jaroslav@1890: this.acc = AccessController.getContext(); jaroslav@1890: this.ccl = Thread.currentThread().getContextClassLoader(); jaroslav@1890: } jaroslav@1890: jaroslav@1890: public Thread newThread(final Runnable r) { jaroslav@1890: return super.newThread(new Runnable() { jaroslav@1890: public void run() { jaroslav@1890: AccessController.doPrivileged(new PrivilegedAction() { jaroslav@1890: public Void run() { jaroslav@1890: Thread.currentThread().setContextClassLoader(ccl); jaroslav@1890: r.run(); jaroslav@1890: return null; jaroslav@1890: } jaroslav@1890: }, acc); jaroslav@1890: } jaroslav@1890: }); jaroslav@1890: } jaroslav@1890: } jaroslav@1890: jaroslav@1890: /** jaroslav@1890: * A wrapper class that exposes only the ExecutorService methods jaroslav@1890: * of an ExecutorService implementation. jaroslav@1890: */ jaroslav@1890: static class DelegatedExecutorService extends AbstractExecutorService { jaroslav@1890: private final ExecutorService e; jaroslav@1890: DelegatedExecutorService(ExecutorService executor) { e = executor; } jaroslav@1890: public void execute(Runnable command) { e.execute(command); } jaroslav@1890: public void shutdown() { e.shutdown(); } jaroslav@1890: public List shutdownNow() { return e.shutdownNow(); } jaroslav@1890: public boolean isShutdown() { return e.isShutdown(); } jaroslav@1890: public boolean isTerminated() { return e.isTerminated(); } jaroslav@1890: public boolean awaitTermination(long timeout, TimeUnit unit) jaroslav@1890: throws InterruptedException { jaroslav@1890: return e.awaitTermination(timeout, unit); jaroslav@1890: } jaroslav@1890: public Future submit(Runnable task) { jaroslav@1890: return e.submit(task); jaroslav@1890: } jaroslav@1890: public Future submit(Callable task) { jaroslav@1890: return e.submit(task); jaroslav@1890: } jaroslav@1890: public Future submit(Runnable task, T result) { jaroslav@1890: return e.submit(task, result); jaroslav@1890: } jaroslav@1890: public List> invokeAll(Collection> tasks) jaroslav@1890: throws InterruptedException { jaroslav@1890: return e.invokeAll(tasks); jaroslav@1890: } jaroslav@1890: public List> invokeAll(Collection> tasks, jaroslav@1890: long timeout, TimeUnit unit) jaroslav@1890: throws InterruptedException { jaroslav@1890: return e.invokeAll(tasks, timeout, unit); jaroslav@1890: } jaroslav@1890: public T invokeAny(Collection> tasks) jaroslav@1890: throws InterruptedException, ExecutionException { jaroslav@1890: return e.invokeAny(tasks); jaroslav@1890: } jaroslav@1890: public T invokeAny(Collection> tasks, jaroslav@1890: long timeout, TimeUnit unit) jaroslav@1890: throws InterruptedException, ExecutionException, TimeoutException { jaroslav@1890: return e.invokeAny(tasks, timeout, unit); jaroslav@1890: } jaroslav@1890: } jaroslav@1890: jaroslav@1890: static class FinalizableDelegatedExecutorService jaroslav@1890: extends DelegatedExecutorService { jaroslav@1890: FinalizableDelegatedExecutorService(ExecutorService executor) { jaroslav@1890: super(executor); jaroslav@1890: } jaroslav@1890: protected void finalize() { jaroslav@1890: super.shutdown(); jaroslav@1890: } jaroslav@1890: } jaroslav@1890: jaroslav@1890: /** jaroslav@1890: * A wrapper class that exposes only the ScheduledExecutorService jaroslav@1890: * methods of a ScheduledExecutorService implementation. jaroslav@1890: */ jaroslav@1890: static class DelegatedScheduledExecutorService jaroslav@1890: extends DelegatedExecutorService jaroslav@1890: implements ScheduledExecutorService { jaroslav@1890: private final ScheduledExecutorService e; jaroslav@1890: DelegatedScheduledExecutorService(ScheduledExecutorService executor) { jaroslav@1890: super(executor); jaroslav@1890: e = executor; jaroslav@1890: } jaroslav@1890: public ScheduledFuture schedule(Runnable command, long delay, TimeUnit unit) { jaroslav@1890: return e.schedule(command, delay, unit); jaroslav@1890: } jaroslav@1890: public ScheduledFuture schedule(Callable callable, long delay, TimeUnit unit) { jaroslav@1890: return e.schedule(callable, delay, unit); jaroslav@1890: } jaroslav@1890: public ScheduledFuture scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit) { jaroslav@1890: return e.scheduleAtFixedRate(command, initialDelay, period, unit); jaroslav@1890: } jaroslav@1890: public ScheduledFuture scheduleWithFixedDelay(Runnable command, long initialDelay, long delay, TimeUnit unit) { jaroslav@1890: return e.scheduleWithFixedDelay(command, initialDelay, delay, unit); jaroslav@1890: } jaroslav@1890: } jaroslav@1890: jaroslav@1890: jaroslav@1890: /** Cannot instantiate. */ jaroslav@1890: private Executors() {} jaroslav@1890: }