ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/main/java/util/concurrent/Executors.java
Revision: 1.23
Committed: Fri Nov 7 12:19:35 2003 UTC (20 years, 6 months ago) by dl
Branch: MAIN
Changes since 1.22: +3 -6 lines
Log Message:
Clarified PFT documentation

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}, {@link ThreadFactory}, {@link Future}, and {@link
18 * Cancellable} classes defined in this package.
19 *
20 * @since 1.5
21 * @author Doug Lea
22 */
23 public class Executors {
24
25 /**
26 * A wrapper class that exposes only the ExecutorService methods
27 * of an implementation.
28 */
29 private static class DelegatedExecutorService implements ExecutorService {
30 private final ExecutorService e;
31 DelegatedExecutorService(ExecutorService executor) { e = executor; }
32 public void execute(Runnable command) { e.execute(command); }
33 public void shutdown() { e.shutdown(); }
34 public List shutdownNow() { return e.shutdownNow(); }
35 public boolean isShutdown() { return e.isShutdown(); }
36 public boolean isTerminated() { return e.isTerminated(); }
37 public boolean awaitTermination(long timeout, TimeUnit unit)
38 throws InterruptedException {
39 return e.awaitTermination(timeout, unit);
40 }
41 }
42
43 /**
44 * Creates a thread pool that reuses a fixed set of threads
45 * operating off a shared unbounded queue. If any thread
46 * terminates due to a failure during execution prior to shutdown,
47 * a new one will take its place if needed to execute subsequent
48 * tasks.
49 *
50 * @param nThreads the number of threads in the pool
51 * @return the newly created thread pool
52 */
53 public static ExecutorService newFixedThreadPool(int nThreads) {
54 return new DelegatedExecutorService
55 (new ThreadPoolExecutor(nThreads, nThreads,
56 0L, TimeUnit.MILLISECONDS,
57 new LinkedBlockingQueue<Runnable>()));
58 }
59
60 /**
61 * Creates a thread pool that reuses a fixed set of threads
62 * operating off a shared unbounded queue, using the provided
63 * ThreadFactory to create new threads when needed.
64 *
65 * @param nThreads the number of threads in the pool
66 * @param threadFactory the factory to use when creating new threads
67 * @return the newly created thread pool
68 */
69 public static ExecutorService newFixedThreadPool(int nThreads, ThreadFactory threadFactory) {
70 return new DelegatedExecutorService
71 (new ThreadPoolExecutor(nThreads, nThreads,
72 0L, TimeUnit.MILLISECONDS,
73 new LinkedBlockingQueue<Runnable>(),
74 threadFactory));
75 }
76
77 /**
78 * Creates an Executor that uses a single worker thread operating
79 * off an unbounded queue. (Note however that if this single
80 * thread terminates due to a failure during execution prior to
81 * shutdown, a new one will take its place if needed to execute
82 * subsequent tasks.) Tasks are guaranteed to execute
83 * sequentially, and no more than one task will be active at any
84 * given time. This method is equivalent in effect to
85 *<tt>new FixedThreadPool(1)</tt>.
86 *
87 * @return the newly-created single-threaded Executor
88 */
89 public static ExecutorService newSingleThreadExecutor() {
90 return new DelegatedExecutorService
91 (new ThreadPoolExecutor(1, 1,
92 0L, TimeUnit.MILLISECONDS,
93 new LinkedBlockingQueue<Runnable>()));
94 }
95
96 /**
97 * Creates an Executor that uses a single worker thread operating
98 * off an unbounded queue, and uses the provided ThreadFactory to
99 * create new threads when needed.
100 * @param threadFactory the factory to use when creating new
101 * threads
102 *
103 * @return the newly-created single-threaded Executor
104 */
105 public static ExecutorService newSingleThreadExecutor(ThreadFactory threadFactory) {
106 return new DelegatedExecutorService
107 (new ThreadPoolExecutor(1, 1,
108 0L, TimeUnit.MILLISECONDS,
109 new LinkedBlockingQueue<Runnable>(),
110 threadFactory));
111 }
112
113 /**
114 * Creates a thread pool that creates new threads as needed, but
115 * will reuse previously constructed threads when they are
116 * available. These pools will typically improve the performance
117 * of programs that execute many short-lived asynchronous tasks.
118 * Calls to <tt>execute</tt> will reuse previously constructed
119 * threads if available. If no existing thread is available, a new
120 * thread will be created and added to the pool. Threads that have
121 * not been used for sixty seconds are terminated and removed from
122 * the cache. Thus, a pool that remains idle for long enough will
123 * not consume any resources. Note that pools with similar
124 * properties but different details (for example, timeout parameters)
125 * may be created using {@link ThreadPoolExecutor} constructors.
126 *
127 * @return the newly created thread pool
128 */
129 public static ExecutorService newCachedThreadPool() {
130 return new DelegatedExecutorService
131 (new ThreadPoolExecutor(0, Integer.MAX_VALUE,
132 60, TimeUnit.SECONDS,
133 new SynchronousQueue<Runnable>()));
134 }
135
136 /**
137 * Creates a thread pool that creates new threads as needed, but
138 * will reuse previously constructed threads when they are
139 * available, and uses the provided
140 * ThreadFactory to create new threads when needed.
141 * @param threadFactory the factory to use when creating new threads
142 * @return the newly created thread pool
143 */
144 public static ExecutorService newCachedThreadPool(ThreadFactory threadFactory) {
145 return new DelegatedExecutorService
146 (new ThreadPoolExecutor(0, Integer.MAX_VALUE,
147 60, TimeUnit.SECONDS,
148 new SynchronousQueue<Runnable>(),
149 threadFactory));
150 }
151
152 /**
153 * Executes a Runnable task and returns a Cancellable representing that
154 * task.
155 *
156 * @param executor the Executor to which the task will be submitted
157 * @param task the task to submit
158 * @return a Cancellable representing pending completion of the task
159 * @throws RejectedExecutionException if task cannot be scheduled
160 * for execution
161 */
162 public static Cancellable execute(Executor executor, Runnable task) {
163 FutureTask<Boolean> ftask = new FutureTask<Boolean>(task, Boolean.TRUE);
164 executor.execute(ftask);
165 return ftask;
166 }
167
168 /**
169 * Executes a Runnable task and returns a Future representing that
170 * task.
171 *
172 * @param executor the Executor to which the task will be submitted
173 * @param task the task to submit
174 * @param value the value which will become the return value of
175 * the task upon task completion
176 * @return a Future representing pending completion of the task
177 * @throws RejectedExecutionException if task cannot be scheduled
178 * for execution
179 */
180 public static <T> Future<T> execute(Executor executor, Runnable task, T value) {
181 FutureTask<T> ftask = new FutureTask<T>(task, value);
182 executor.execute(ftask);
183 return ftask;
184 }
185
186 /**
187 * Executes a value-returning task and returns a Future
188 * representing the pending results of the task.
189 *
190 * @param executor the Executor to which the task will be submitted
191 * @param task the task to submit
192 * @return a Future representing pending completion of the task
193 * @throws RejectedExecutionException if task cannot be scheduled
194 * for execution
195 */
196 public static <T> Future<T> execute(Executor executor, Callable<T> task) {
197 FutureTask<T> ftask = new FutureTask<T>(task);
198 executor.execute(ftask);
199 return ftask;
200 }
201
202 /**
203 * Executes a Runnable task and blocks until it completes normally
204 * or throws an exception.
205 *
206 * @param executor the Executor to which the task will be submitted
207 * @param task the task to submit
208 * @throws RejectedExecutionException if task cannot be scheduled
209 * for execution
210 * @throws ExecutionException if the task encountered an exception
211 * while executing
212 */
213 public static void invoke(Executor executor, Runnable task)
214 throws ExecutionException, InterruptedException {
215 FutureTask<Boolean> ftask = new FutureTask<Boolean>(task, Boolean.TRUE);
216 executor.execute(ftask);
217 ftask.get();
218 }
219
220 /**
221 * Executes a value-returning task and blocks until it returns a
222 * value or throws an exception.
223 *
224 * @param executor the Executor to which the task will be submitted
225 * @param task the task to submit
226 * @return a Future representing pending completion of the task
227 * @throws RejectedExecutionException if task cannot be scheduled
228 * for execution
229 * @throws InterruptedException if interrupted while waiting for
230 * completion
231 * @throws ExecutionException if the task encountered an exception
232 * while executing
233 */
234 public static <T> T invoke(Executor executor, Callable<T> task)
235 throws ExecutionException, InterruptedException {
236 FutureTask<T> ftask = new FutureTask<T>(task);
237 executor.execute(ftask);
238 return ftask.get();
239 }
240
241
242 /**
243 * Executes a privileged action under the current access control
244 * context and returns a Future representing the pending result
245 * object of that action.
246 *
247 * @param executor the Executor to which the task will be submitted
248 * @param action the action to submit
249 * @return a Future representing pending completion of the action
250 * @throws RejectedExecutionException if action cannot be scheduled
251 * for execution
252 */
253 public static Future<Object> execute(Executor executor, PrivilegedAction action) {
254 Callable<Object> task = new PrivilegedActionAdapter(action);
255 FutureTask<Object> future = new PrivilegedFutureTask<Object>(task);
256 executor.execute(future);
257 return future;
258 }
259
260 /**
261 * Executes a privileged exception action under the current access control
262 * context and returns a Future representing the pending result
263 * object of that action.
264 *
265 * @param executor the Executor to which the task will be submitted
266 * @param action the action to submit
267 * @return a Future representing pending completion of the action
268 * @throws RejectedExecutionException if action cannot be scheduled
269 * for execution
270 */
271 public static Future<Object> execute(Executor executor, PrivilegedExceptionAction action) {
272 Callable<Object> task = new PrivilegedExceptionActionAdapter(action);
273 FutureTask<Object> future = new PrivilegedFutureTask<Object>(task);
274 executor.execute(future);
275 return future;
276 }
277
278 private static class PrivilegedActionAdapter implements Callable<Object> {
279 PrivilegedActionAdapter(PrivilegedAction action) {
280 this.action = action;
281 }
282 public Object call () {
283 return action.run();
284 }
285 private final PrivilegedAction action;
286 }
287
288 private static class PrivilegedExceptionActionAdapter implements Callable<Object> {
289 PrivilegedExceptionActionAdapter(PrivilegedExceptionAction action) {
290 this.action = action;
291 }
292 public Object call () throws Exception {
293 return action.run();
294 }
295 private final PrivilegedExceptionAction action;
296 }
297
298 /**
299 * Return a default thread factory used to create new threads.
300 * This factory creates all new threads used by an Executor in the
301 * same {@link ThreadGroup}. If there is a {@link
302 * java.lang.SecurityManager}, it uses the group of {@link
303 * System#getSecurityManager}, else the group of the thread
304 * invoking this <tt>defaultThreadFactory</tt> method. Each new
305 * thread is created as a non-daemon thread with priority
306 * <tt>Thread.NORM_PRIORITY</tt>. New threads have names
307 * accessible via {@link Thread#getName} of
308 * <em>pool-N-thread-M</em>, where <em>N</em> is the sequence
309 * number of this factory, and <em>M</em> is the sequence number
310 * of the thread created by this factory.
311 * @return the thread factory
312 */
313 public static ThreadFactory defaultThreadFactory() {
314 return new DefaultThreadFactory();
315 }
316
317 /**
318 * Return a default thread factory used to create new threads.
319 * This factory creates threads with the same settings as {@link
320 * Executors#defaultThreadFactory}, additionally setting the
321 * AccessControlContext and contextClassLoader of new threads to
322 * be the same as the thread invoking this
323 * <tt>privilegedThreadFactory</tt> method. A new
324 * <tt>privilegedThreadFactory</tt> can be created within an
325 * {@link AccessController#doPrivileged} action setting the
326 * current threads access control context to create threads with
327 * the selected permission settings holding within that action.
328 *
329 * <p> Note that while tasks running within such threads will have
330 * the same access control and class loader settings as the
331 * current thread, they need not have the same {@link
332 * java.lang.ThreadLocal} or {@link
333 * java.lang.InheritableThreadLocal} values. If necessary,
334 * particular values of thread locals can be set or reset before
335 * any task runs in {@link ThreadPoolExecutor} subclasses using
336 * {@link ThreadPoolExecutor#beforeExecute}. Also, if it is
337 * necessary to initialize worker threads to have the same
338 * InheritableThreadLocal settings as some other designated
339 * thread, you can create a custom ThreadFactory in which that
340 * thread waits for and services requests to create others that
341 * will inherit its values.
342 *
343 * @return the thread factory
344 * @throws AccessControlException if the current access control
345 * context does not have permission to both get and set context
346 * class loader.
347 * @see PrivilegedFutureTask
348 */
349 public static ThreadFactory privilegedThreadFactory() {
350 return new PrivilegedThreadFactory();
351 }
352
353 static class DefaultThreadFactory implements ThreadFactory {
354 static final AtomicInteger poolNumber = new AtomicInteger(1);
355 final ThreadGroup group;
356 final AtomicInteger threadNumber = new AtomicInteger(1);
357 final String namePrefix;
358
359 DefaultThreadFactory() {
360 SecurityManager s = System.getSecurityManager();
361 group = (s != null)? s.getThreadGroup() :
362 Thread.currentThread().getThreadGroup();
363 namePrefix = "pool-" +
364 poolNumber.getAndIncrement() +
365 "-thread-";
366 }
367
368 public Thread newThread(Runnable r) {
369 Thread t = new Thread(group, r,
370 namePrefix + threadNumber.getAndIncrement(),
371 0);
372 if (t.isDaemon())
373 t.setDaemon(false);
374 if (t.getPriority() != Thread.NORM_PRIORITY)
375 t.setPriority(Thread.NORM_PRIORITY);
376 return t;
377 }
378 }
379
380 static class PrivilegedThreadFactory extends DefaultThreadFactory {
381 private final ClassLoader ccl;
382 private final AccessControlContext acc;
383
384 PrivilegedThreadFactory() {
385 super();
386 this.ccl = Thread.currentThread().getContextClassLoader();
387 this.acc = AccessController.getContext();
388 acc.checkPermission(new RuntimePermission("setContextClassLoader"));
389 }
390
391 public Thread newThread(final Runnable r) {
392 return super.newThread(new Runnable() {
393 public void run() {
394 AccessController.doPrivileged(new PrivilegedAction() {
395 public Object run() {
396 Thread.currentThread().setContextClassLoader(ccl);
397 r.run();
398 return null;
399 }
400 }, acc);
401 }
402 });
403 }
404
405 }
406
407
408 /** Cannot instantiate. */
409 private Executors() {}
410 }