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