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

# User Rev Content
1 tim 1.1 /*
2 dl 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 tim 1.1 */
6    
7     package java.util.concurrent;
8 dl 1.2 import java.util.*;
9 dl 1.22 import java.util.concurrent.atomic.AtomicInteger;
10 tim 1.20 import java.security.AccessControlContext;
11     import java.security.AccessController;
12     import java.security.PrivilegedAction;
13     import java.security.PrivilegedExceptionAction;
14 tim 1.1
15     /**
16 dl 1.18 * Factory and utility methods for {@link Executor}, {@link
17 dl 1.25 * ExecutorService}, {@link ThreadFactory}, and {@link Future}
18     * classes defined in this package.
19 tim 1.1 *
20     * @since 1.5
21 dl 1.12 * @author Doug Lea
22 tim 1.1 */
23     public class Executors {
24    
25     /**
26 dl 1.2 * A wrapper class that exposes only the ExecutorService methods
27     * of an implementation.
28 tim 1.6 */
29 jozart 1.11 private static class DelegatedExecutorService implements ExecutorService {
30 dl 1.2 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 tim 1.26
43     /**
44     * A wrapper class that exposes only the ExecutorService and
45     * ScheduleExecutor methods of a ScheduledThreadPoolExecutor.
46     */
47 tim 1.27 private static class DelegatedScheduledExecutorService
48 tim 1.28 extends DelegatedExecutorService
49     implements ScheduledExecutorService {
50 tim 1.26 private final ScheduledExecutor e;
51 tim 1.28 DelegatedScheduledExecutorService(ScheduledExecutorService executor) {
52 tim 1.26 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 dl 1.2
69     /**
70 tim 1.1 * Creates a thread pool that reuses a fixed set of threads
71 dl 1.16 * 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 tim 1.1 *
76     * @param nThreads the number of threads in the pool
77     * @return the newly created thread pool
78     */
79 dl 1.2 public static ExecutorService newFixedThreadPool(int nThreads) {
80     return new DelegatedExecutorService
81     (new ThreadPoolExecutor(nThreads, nThreads,
82     0L, TimeUnit.MILLISECONDS,
83 dl 1.3 new LinkedBlockingQueue<Runnable>()));
84 dl 1.2 }
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 dl 1.12 * @param threadFactory the factory to use when creating new threads
93 dl 1.2 * @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 dl 1.3 new LinkedBlockingQueue<Runnable>(),
100 dl 1.14 threadFactory));
101 dl 1.2 }
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 dl 1.16 * given time. This method is equivalent in effect to
111     *<tt>new FixedThreadPool(1)</tt>.
112 dl 1.2 *
113     * @return the newly-created single-threaded Executor
114     */
115     public static ExecutorService newSingleThreadExecutor() {
116     return new DelegatedExecutorService
117 tim 1.6 (new ThreadPoolExecutor(1, 1,
118 dl 1.2 0L, TimeUnit.MILLISECONDS,
119 dl 1.3 new LinkedBlockingQueue<Runnable>()));
120 dl 1.2 }
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 dl 1.12 * @param threadFactory the factory to use when creating new
127 dl 1.2 * threads
128     *
129     * @return the newly-created single-threaded Executor
130     */
131     public static ExecutorService newSingleThreadExecutor(ThreadFactory threadFactory) {
132     return new DelegatedExecutorService
133 tim 1.6 (new ThreadPoolExecutor(1, 1,
134 dl 1.2 0L, TimeUnit.MILLISECONDS,
135 dl 1.3 new LinkedBlockingQueue<Runnable>(),
136 dl 1.14 threadFactory));
137 tim 1.1 }
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 dl 1.16 * 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 tim 1.1 *
153     * @return the newly created thread pool
154     */
155 dl 1.2 public static ExecutorService newCachedThreadPool() {
156     return new DelegatedExecutorService
157     (new ThreadPoolExecutor(0, Integer.MAX_VALUE,
158     60, TimeUnit.SECONDS,
159 dl 1.3 new SynchronousQueue<Runnable>()));
160 tim 1.1 }
161    
162     /**
163 dl 1.2 * Creates a thread pool that creates new threads as needed, but
164     * will reuse previously constructed threads when they are
165 tim 1.6 * available, and uses the provided
166 dl 1.2 * ThreadFactory to create new threads when needed.
167 dl 1.12 * @param threadFactory the factory to use when creating new threads
168 tim 1.1 * @return the newly created thread pool
169     */
170 dl 1.2 public static ExecutorService newCachedThreadPool(ThreadFactory threadFactory) {
171     return new DelegatedExecutorService
172     (new ThreadPoolExecutor(0, Integer.MAX_VALUE,
173     60, TimeUnit.SECONDS,
174 dl 1.3 new SynchronousQueue<Runnable>(),
175 dl 1.14 threadFactory));
176 tim 1.1 }
177 tim 1.27
178 tim 1.26 /**
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 tim 1.28 public static ScheduledExecutorService newScheduledThreadPool() {
185 tim 1.27 return newScheduledThreadPool(1);
186 tim 1.26 }
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 tim 1.28 public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {
197 tim 1.27 return new DelegatedScheduledExecutorService
198     (new ScheduledThreadPoolExecutor(corePoolSize));
199 tim 1.26 }
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 tim 1.28 public static ScheduledExecutorService newScheduledThreadPool(
212     int corePoolSize, ThreadFactory threadFactory) {
213 tim 1.27 return new DelegatedScheduledExecutorService
214     (new ScheduledThreadPoolExecutor(corePoolSize, threadFactory));
215 tim 1.26 }
216 tim 1.1
217     /**
218 dl 1.25 * Executes a Runnable task and returns a Future representing that
219 tim 1.15 * task.
220     *
221     * @param executor the Executor to which the task will be submitted
222     * @param task the task to submit
223 dl 1.25 * @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 tim 1.15 * @throws RejectedExecutionException if task cannot be scheduled
227     * for execution
228     */
229 dl 1.25 public static Future<Boolean> execute(Executor executor, Runnable task) {
230 tim 1.15 FutureTask<Boolean> ftask = new FutureTask<Boolean>(task, Boolean.TRUE);
231     executor.execute(ftask);
232     return ftask;
233     }
234    
235     /**
236 tim 1.1 * 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 dl 1.5 * @return a Future representing pending completion of the task
244 jozart 1.9 * @throws RejectedExecutionException if task cannot be scheduled
245 tim 1.1 * for execution
246     */
247 dl 1.5 public static <T> Future<T> execute(Executor executor, Runnable task, T value) {
248 dl 1.10 FutureTask<T> ftask = new FutureTask<T>(task, value);
249 tim 1.1 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 jozart 1.9 * @throws RejectedExecutionException if task cannot be scheduled
261     * for execution
262 tim 1.1 */
263 tim 1.15 public static <T> Future<T> execute(Executor executor, Callable<T> task) {
264 dl 1.10 FutureTask<T> ftask = new FutureTask<T>(task);
265 tim 1.1 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 jozart 1.9 * @throws RejectedExecutionException if task cannot be scheduled
276     * for execution
277 dl 1.19 * @throws ExecutionException if the task encountered an exception
278     * while executing
279 tim 1.1 */
280     public static void invoke(Executor executor, Runnable task)
281     throws ExecutionException, InterruptedException {
282 tim 1.13 FutureTask<Boolean> ftask = new FutureTask<Boolean>(task, Boolean.TRUE);
283 tim 1.1 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 jozart 1.9 * @throws RejectedExecutionException if task cannot be scheduled
295     * for execution
296 dl 1.12 * @throws InterruptedException if interrupted while waiting for
297     * completion
298 dl 1.19 * @throws ExecutionException if the task encountered an exception
299     * while executing
300 tim 1.1 */
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 tim 1.6 }
307    
308 tim 1.20
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 tim 1.21 FutureTask<Object> future = new PrivilegedFutureTask<Object>(task);
323 tim 1.20 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 tim 1.21 FutureTask<Object> future = new PrivilegedFutureTask<Object>(task);
341 tim 1.20 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 dl 1.22 /**
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 tim 1.26 return new DefaultThreadFactory();
382 dl 1.22 }
383    
384     /**
385 dl 1.24 * Return a thread factory used to create new threads that
386     * have the same permissions as the current thread.
387 dl 1.22 * 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 dl 1.23 * {@link AccessController#doPrivileged} action setting the
394 dl 1.24 * current thread's access control context to create threads with
395 dl 1.23 * the selected permission settings holding within that action.
396 dl 1.22 *
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 tim 1.26 return new PrivilegedThreadFactory();
419 dl 1.22 }
420    
421     static class DefaultThreadFactory implements ThreadFactory {
422 tim 1.26 static final AtomicInteger poolNumber = new AtomicInteger(1);
423     final ThreadGroup group;
424     final AtomicInteger threadNumber = new AtomicInteger(1);
425     final String namePrefix;
426 dl 1.22
427 tim 1.26 DefaultThreadFactory() {
428 dl 1.22 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 tim 1.20
476 tim 1.15 /** Cannot instantiate. */
477     private Executors() {}
478 tim 1.1 }