ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/main/java/util/concurrent/Executors.java
Revision: 1.28
Committed: Sun Dec 7 14:57:46 2003 UTC (20 years, 6 months ago) by tim
Branch: MAIN
Changes since 1.27: +7 -6 lines
Log Message:
ScheduledExecutorService for Executors factory method return type

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