ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/main/java/util/concurrent/Executors.java
Revision: 1.27
Committed: Sat Dec 6 04:31:03 2003 UTC (20 years, 6 months ago) by tim
Branch: MAIN
Changes since 1.26: +8 -48 lines
Log Message:
Removed one of the newScheduledThreadPool factory methods

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