ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/main/java/util/concurrent/Executors.java
Revision: 1.40
Committed: Sat Dec 20 15:48:27 2003 UTC (20 years, 9 months ago) by dl
Branch: MAIN
Changes since 1.39: +53 -17 lines
Log Message:
rename ScheduledExecutorService factory methods; minor doc touch-ups

File Contents

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