ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/main/java/util/concurrent/Executors.java
Revision: 1.36
Committed: Wed Dec 17 17:00:24 2003 UTC (20 years, 5 months ago) by dl
Branch: MAIN
Changes since 1.35: +146 -10 lines
Log Message:
Export delegation wrappers; fix/add 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}, 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. The returned executor cannot be reconfigured
65 * to use additional threads.
66 *
67 * @return the newly-created single-threaded Executor
68 */
69 public static ExecutorService newSingleThreadExecutor() {
70 return unconfigurableExecutorService
71 (new ThreadPoolExecutor(1, 1,
72 0L, TimeUnit.MILLISECONDS,
73 new LinkedBlockingQueue<Runnable>()));
74 }
75
76 /**
77 * Creates an Executor that uses a single worker thread operating
78 * off an unbounded queue, and uses the provided ThreadFactory to
79 * create a new thread when needed. The returned executor cannot be
80 * reconfigured to use additional threads.
81 * @param threadFactory the factory to use when creating new
82 * threads
83 *
84 * @return the newly-created single-threaded Executor
85 */
86 public static ExecutorService newSingleThreadExecutor(ThreadFactory threadFactory) {
87 return unconfigurableExecutorService
88 (new ThreadPoolExecutor(1, 1,
89 0L, TimeUnit.MILLISECONDS,
90 new LinkedBlockingQueue<Runnable>(),
91 threadFactory));
92 }
93
94 /**
95 * Creates a thread pool that creates new threads as needed, but
96 * will reuse previously constructed threads when they are
97 * available. These pools will typically improve the performance
98 * of programs that execute many short-lived asynchronous tasks.
99 * Calls to <tt>execute</tt> will reuse previously constructed
100 * threads if available. If no existing thread is available, a new
101 * thread will be created and added to the pool. Threads that have
102 * not been used for sixty seconds are terminated and removed from
103 * the cache. Thus, a pool that remains idle for long enough will
104 * not consume any resources. Note that pools with similar
105 * properties but different details (for example, timeout parameters)
106 * may be created using {@link ThreadPoolExecutor} constructors.
107 *
108 * @return the newly created thread pool
109 */
110 public static ExecutorService newCachedThreadPool() {
111 return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
112 60, TimeUnit.SECONDS,
113 new SynchronousQueue<Runnable>());
114 }
115
116 /**
117 * Creates a thread pool that creates new threads as needed, but
118 * will reuse previously constructed threads when they are
119 * available, and uses the provided
120 * ThreadFactory to create new threads when needed.
121 * @param threadFactory the factory to use when creating new threads
122 * @return the newly created thread pool
123 */
124 public static ExecutorService newCachedThreadPool(ThreadFactory threadFactory) {
125 return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
126 60, TimeUnit.SECONDS,
127 new SynchronousQueue<Runnable>(),
128 threadFactory);
129 }
130
131 /**
132 * Creates a thread pool that can schedule commands to run after a
133 * given delay, or to execute periodically.
134 * @return a newly created scheduled thread pool with termination management
135 */
136 public static ScheduledExecutorService newScheduledThreadPool() {
137 return newScheduledThreadPool(1);
138 }
139
140 /**
141 * Creates a thread pool that can schedule commands to run after a
142 * given delay, or to execute periodically.
143 * @param corePoolSize the number of threads to keep in the pool,
144 * even if they are idle.
145 * @return a newly created scheduled thread pool with termination management
146 */
147 public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {
148 return new ScheduledThreadPoolExecutor(corePoolSize);
149 }
150
151 /**
152 * Creates a thread pool that can schedule commands to run after a
153 * given delay, or to execute periodically.
154 * @param corePoolSize the number of threads to keep in the pool,
155 * even if they are idle.
156 * @param threadFactory the factory to use when the executor
157 * creates a new thread.
158 * @return a newly created scheduled thread pool with termination management
159 */
160 public static ScheduledExecutorService newScheduledThreadPool(
161 int corePoolSize, ThreadFactory threadFactory) {
162 return new ScheduledThreadPoolExecutor(corePoolSize, threadFactory);
163 }
164
165
166 /**
167 * Creates and returns an object that delegates all defined {@link
168 * ExecutorService} methods to the given executor, but not any
169 * other methods that might otherwise be accessible using
170 * casts. This provides a way to safely "freeze" configuration and
171 * disallow tuning of a given concrete implementation.
172 * @param executor the underlying implementation
173 * @return an <tt>ExecutorService</tt> instance
174 * @throws NullPointerException if executor null
175 */
176 public static ExecutorService unconfigurableExecutorService(ExecutorService executor) {
177 if (executor == null)
178 throw new NullPointerException();
179 return new DelegatedExecutorService(executor);
180 }
181
182 /**
183 * Creates and returns an object that delegates all defined {@link
184 * ScheduledExecutorService} methods to the given executor, but
185 * not any other methods that might otherwise be accessible using
186 * casts. This provides a way to safely "freeze" configuration and
187 * disallow tuning of a given concrete implementation.
188 * @param executor the underlying implementation
189 * @return a <tt>ScheduledExecutorService</tt> instance
190 * @throws NullPointerException if executor null
191 */
192 public static ScheduledExecutorService unconfigurableScheduledExecutorService(ScheduledExecutorService executor) {
193 if (executor == null)
194 throw new NullPointerException();
195 return new DelegatedScheduledExecutorService(executor);
196 }
197
198 /**
199 * Return a default thread factory used to create new threads.
200 * This factory creates all new threads used by an Executor in the
201 * same {@link ThreadGroup}. If there is a {@link
202 * java.lang.SecurityManager}, it uses the group of {@link
203 * System#getSecurityManager}, else the group of the thread
204 * invoking this <tt>defaultThreadFactory</tt> method. Each new
205 * thread is created as a non-daemon thread with priority
206 * <tt>Thread.NORM_PRIORITY</tt>. New threads have names
207 * accessible via {@link Thread#getName} of
208 * <em>pool-N-thread-M</em>, where <em>N</em> is the sequence
209 * number of this factory, and <em>M</em> is the sequence number
210 * of the thread created by this factory.
211 * @return the thread factory
212 */
213 public static ThreadFactory defaultThreadFactory() {
214 return new DefaultThreadFactory();
215 }
216
217 /**
218 * Return a thread factory used to create new threads that
219 * have the same permissions as the current thread.
220 * This factory creates threads with the same settings as {@link
221 * Executors#defaultThreadFactory}, additionally setting the
222 * AccessControlContext and contextClassLoader of new threads to
223 * be the same as the thread invoking this
224 * <tt>privilegedThreadFactory</tt> method. A new
225 * <tt>privilegedThreadFactory</tt> can be created within an
226 * {@link AccessController#doPrivileged} action setting the
227 * current thread's access control context to create threads with
228 * the selected permission settings holding within that action.
229 *
230 * <p> Note that while tasks running within such threads will have
231 * the same access control and class loader settings as the
232 * current thread, they need not have the same {@link
233 * java.lang.ThreadLocal} or {@link
234 * java.lang.InheritableThreadLocal} values. If necessary,
235 * particular values of thread locals can be set or reset before
236 * any task runs in {@link ThreadPoolExecutor} subclasses using
237 * {@link ThreadPoolExecutor#beforeExecute}. Also, if it is
238 * necessary to initialize worker threads to have the same
239 * InheritableThreadLocal settings as some other designated
240 * thread, you can create a custom ThreadFactory in which that
241 * thread waits for and services requests to create others that
242 * will inherit its values.
243 *
244 * @return the thread factory
245 * @throws AccessControlException if the current access control
246 * context does not have permission to both get and set context
247 * class loader.
248 * @see PrivilegedFutureTask
249 */
250 public static ThreadFactory privilegedThreadFactory() {
251 return new PrivilegedThreadFactory();
252 }
253
254 static class DefaultThreadFactory implements ThreadFactory {
255 static final AtomicInteger poolNumber = new AtomicInteger(1);
256 final ThreadGroup group;
257 final AtomicInteger threadNumber = new AtomicInteger(1);
258 final String namePrefix;
259
260 DefaultThreadFactory() {
261 SecurityManager s = System.getSecurityManager();
262 group = (s != null)? s.getThreadGroup() :
263 Thread.currentThread().getThreadGroup();
264 namePrefix = "pool-" +
265 poolNumber.getAndIncrement() +
266 "-thread-";
267 }
268
269 public Thread newThread(Runnable r) {
270 Thread t = new Thread(group, r,
271 namePrefix + threadNumber.getAndIncrement(),
272 0);
273 if (t.isDaemon())
274 t.setDaemon(false);
275 if (t.getPriority() != Thread.NORM_PRIORITY)
276 t.setPriority(Thread.NORM_PRIORITY);
277 return t;
278 }
279 }
280
281 static class PrivilegedThreadFactory extends DefaultThreadFactory {
282 private final ClassLoader ccl;
283 private final AccessControlContext acc;
284
285 PrivilegedThreadFactory() {
286 super();
287 this.ccl = Thread.currentThread().getContextClassLoader();
288 this.acc = AccessController.getContext();
289 acc.checkPermission(new RuntimePermission("setContextClassLoader"));
290 }
291
292 public Thread newThread(final Runnable r) {
293 return super.newThread(new Runnable() {
294 public void run() {
295 AccessController.doPrivileged(new PrivilegedAction() {
296 public Object run() {
297 Thread.currentThread().setContextClassLoader(ccl);
298 r.run();
299 return null;
300 }
301 }, acc);
302 }
303 });
304 }
305
306 }
307
308
309 /**
310 * A wrapper class that exposes only the ExecutorService methods
311 * of an implementation.
312 */
313 private static class DelegatedExecutorService extends AbstractExecutorService {
314 private final ExecutorService e;
315 DelegatedExecutorService(ExecutorService executor) { e = executor; }
316 public void execute(Runnable command) { e.execute(command); }
317 public void shutdown() { e.shutdown(); }
318 public List<Runnable> shutdownNow() { return e.shutdownNow(); }
319 public boolean isShutdown() { return e.isShutdown(); }
320 public boolean isTerminated() { return e.isTerminated(); }
321 public boolean awaitTermination(long timeout, TimeUnit unit)
322 throws InterruptedException {
323 return e.awaitTermination(timeout, unit);
324 }
325 public <T> Future<T> submit(Runnable task, T result) {
326 return e.submit(task, result);
327 }
328 public <T> Future<T> submit(Callable<T> task) {
329 return e.submit(task);
330 }
331
332 public void invoke(Runnable task) throws ExecutionException, InterruptedException {
333 e.invoke(task);
334 }
335 public <T> T invoke(Callable<T> task) throws ExecutionException, InterruptedException {
336 return e.invoke(task);
337 }
338 public Future<Object> submit(PrivilegedAction action) {
339 return e.submit(action);
340 }
341 public Future<Object> submit(PrivilegedExceptionAction action) {
342 return e.submit(action);
343 }
344 public <T> List<Future<T>> invokeAll(Collection<Runnable> tasks, T result)
345 throws InterruptedException {
346 return e.invokeAll(tasks, result);
347 }
348 public <T> List<Future<T>> invokeAll(Collection<Runnable> tasks, T result,
349 long timeout, TimeUnit unit)
350 throws InterruptedException {
351 return e.invokeAll(tasks, result, timeout, unit);
352 }
353 public <T> List<Future<T>> invokeAll(Collection<Callable<T>> tasks)
354 throws InterruptedException {
355 return e.invokeAll(tasks);
356 }
357 public <T> List<Future<T>> invokeAll(Collection<Callable<T>> tasks,
358 long timeout, TimeUnit unit)
359 throws InterruptedException {
360 return e.invokeAll(tasks, timeout, unit);
361 }
362 public <T> T invokeAny(Collection<Callable<T>> tasks)
363 throws InterruptedException, ExecutionException {
364 return e.invokeAny(tasks);
365 }
366 public <T> T invokeAny(Collection<Callable<T>> tasks,
367 long timeout, TimeUnit unit)
368 throws InterruptedException, ExecutionException, TimeoutException {
369 return e.invokeAny(tasks, timeout, unit);
370 }
371 public <T> T invokeAny(Collection<Runnable> tasks, T result)
372 throws InterruptedException, ExecutionException {
373 return e.invokeAny(tasks, result);
374 }
375 public <T> T invokeAny(Collection<Runnable> tasks, T result,
376 long timeout, TimeUnit unit)
377 throws InterruptedException, ExecutionException, TimeoutException {
378 return e.invokeAny(tasks, result, timeout, unit);
379 }
380 }
381
382 /**
383 * A wrapper class that exposes only the ExecutorService and
384 * ScheduleExecutor methods of a ScheduledThreadPoolExecutor.
385 */
386 private static class DelegatedScheduledExecutorService
387 extends DelegatedExecutorService
388 implements ScheduledExecutorService {
389 private final ScheduledExecutorService e;
390 DelegatedScheduledExecutorService(ScheduledExecutorService executor) {
391 super(executor);
392 e = executor;
393 }
394 public ScheduledFuture<?> schedule(Runnable command, long delay, TimeUnit unit) {
395 return e.schedule(command, delay, unit);
396 }
397 public <V> ScheduledFuture<V> schedule(Callable<V> callable, long delay, TimeUnit unit) {
398 return e.schedule(callable, delay, unit);
399 }
400 public ScheduledFuture<?> scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit) {
401 return e.scheduleAtFixedRate(command, initialDelay, period, unit);
402 }
403 public ScheduledFuture<?> scheduleWithFixedDelay(Runnable command, long initialDelay, long delay, TimeUnit unit) {
404 return e.scheduleWithFixedDelay(command, initialDelay, delay, unit);
405 }
406 }
407
408
409 /** Cannot instantiate. */
410 private Executors() {}
411 }