ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/main/java/util/concurrent/AbstractExecutorService.java
Revision: 1.30
Committed: Sat Oct 28 00:31:54 2006 UTC (17 years, 7 months ago) by jsr166
Branch: MAIN
Changes since 1.29: +12 -0 lines
Log Message:
6458306: Executor classes missing unchecked exception specs

File Contents

# User Rev Content
1 tim 1.1 /*
2     * Written by Doug Lea with assistance from members of JCP JSR-166
3 dl 1.17 * Expert Group and released to the public domain, as explained at
4     * http://creativecommons.org/licenses/publicdomain
5 tim 1.1 */
6    
7     package java.util.concurrent;
8 dl 1.3 import java.util.*;
9 tim 1.1
10     /**
11 jsr166 1.24 * Provides default implementations of {@link ExecutorService}
12 dl 1.12 * execution methods. This class implements the <tt>submit</tt>,
13 peierls 1.21 * <tt>invokeAny</tt> and <tt>invokeAll</tt> methods using a
14     * {@link RunnableFuture} returned by <tt>newTaskFor</tt>, which defaults
15     * to the {@link FutureTask} class provided in this package. For example,
16 dl 1.18 * the implementation of <tt>submit(Runnable)</tt> creates an
17 peierls 1.21 * associated <tt>RunnableFuture</tt> that is executed and
18     * returned. Subclasses may override the <tt>newTaskFor</tt> methods
19 jsr166 1.24 * to return <tt>RunnableFuture</tt> implementations other than
20 peierls 1.21 * <tt>FutureTask</tt>.
21 tim 1.1 *
22 dl 1.22 * <p> <b>Extension example</b>. Here is a sketch of a class
23     * that customizes {@link ThreadPoolExecutor} to use
24     * a <tt>CustomTask</tt> class instead of the default <tt>FutureTask</tt>:
25     * <pre>
26     * public class CustomThreadPoolExecutor extends ThreadPoolExecutor {
27     *
28 jsr166 1.25 * static class CustomTask&lt;V&gt; implements RunnableFuture&lt;V&gt; {...}
29 dl 1.22 *
30 jsr166 1.25 * protected &lt;V&gt; RunnableFuture&lt;V&gt; newTaskFor(Callable&lt;V&gt; c) {
31     * return new CustomTask&lt;V&gt;(c);
32     * }
33     * protected &lt;V&gt; RunnableFuture&lt;V&gt; newTaskFor(Runnable r, V v) {
34     * return new CustomTask&lt;V&gt;(r, v);
35     * }
36     * // ... add constructors, etc.
37 dl 1.22 * }
38     * </pre>
39 tim 1.1 * @since 1.5
40     * @author Doug Lea
41     */
42     public abstract class AbstractExecutorService implements ExecutorService {
43    
44 peierls 1.21 /**
45     * Returns a <tt>RunnableFuture</tt> for the given runnable and default
46     * value.
47 jsr166 1.24 *
48 peierls 1.21 * @param runnable the runnable task being wrapped
49     * @param value the default value for the returned future
50 dl 1.22 * @return a <tt>RunnableFuture</tt> which when run will run the
51     * underlying runnable and which, as a <tt>Future</tt>, will yield
52     * the given value as its result and provide for cancellation of
53     * the underlying task.
54     * @since 1.6
55 peierls 1.21 */
56     protected <T> RunnableFuture<T> newTaskFor(Runnable runnable, T value) {
57     return new FutureTask<T>(runnable, value);
58     }
59    
60     /**
61     * Returns a <tt>RunnableFuture</tt> for the given callable task.
62 jsr166 1.24 *
63 peierls 1.21 * @param callable the callable task being wrapped
64 dl 1.22 * @return a <tt>RunnableFuture</tt> which when run will call the
65     * underlying callable and which, as a <tt>Future</tt>, will yield
66     * the callable's result as its result and provide for
67     * cancellation of the underlying task.
68     * @since 1.6
69 peierls 1.21 */
70     protected <T> RunnableFuture<T> newTaskFor(Callable<T> callable) {
71     return new FutureTask<T>(callable);
72     }
73    
74 jsr166 1.30 /**
75     * @throws RejectedExecutionException {@inheritDoc}
76     * @throws NullPointerException {@inheritDoc}
77     */
78 dl 1.11 public Future<?> submit(Runnable task) {
79 dl 1.13 if (task == null) throw new NullPointerException();
80 peierls 1.21 RunnableFuture<Object> ftask = newTaskFor(task, null);
81 tim 1.1 execute(ftask);
82     return ftask;
83     }
84    
85 jsr166 1.30 /**
86     * @throws RejectedExecutionException {@inheritDoc}
87     * @throws NullPointerException {@inheritDoc}
88     */
89 dl 1.13 public <T> Future<T> submit(Runnable task, T result) {
90     if (task == null) throw new NullPointerException();
91 peierls 1.21 RunnableFuture<T> ftask = newTaskFor(task, result);
92 dl 1.13 execute(ftask);
93     return ftask;
94     }
95    
96 jsr166 1.30 /**
97     * @throws RejectedExecutionException {@inheritDoc}
98     * @throws NullPointerException {@inheritDoc}
99     */
100 tim 1.1 public <T> Future<T> submit(Callable<T> task) {
101 dl 1.13 if (task == null) throw new NullPointerException();
102 peierls 1.21 RunnableFuture<T> ftask = newTaskFor(task);
103 tim 1.1 execute(ftask);
104     return ftask;
105     }
106    
107 dl 1.15 /**
108     * the main mechanics of invokeAny.
109     */
110 jsr166 1.26 private <T> T doInvokeAny(Collection<? extends Callable<T>> tasks,
111 jsr166 1.29 boolean timed, long nanos)
112 dl 1.15 throws InterruptedException, ExecutionException, TimeoutException {
113 dl 1.3 if (tasks == null)
114     throw new NullPointerException();
115 dl 1.15 int ntasks = tasks.size();
116     if (ntasks == 0)
117 dl 1.7 throw new IllegalArgumentException();
118 dl 1.15 List<Future<T>> futures= new ArrayList<Future<T>>(ntasks);
119 jsr166 1.20 ExecutorCompletionService<T> ecs =
120 dl 1.7 new ExecutorCompletionService<T>(this);
121 dl 1.15
122     // For efficiency, especially in executors with limited
123     // parallelism, check to see if previously submitted tasks are
124 dl 1.18 // done before submitting more of them. This interleaving
125 dl 1.15 // plus the exception mechanics account for messiness of main
126 dl 1.18 // loop.
127 dl 1.15
128 dl 1.3 try {
129 dl 1.15 // Record exceptions so that if we fail to obtain any
130     // result, we can throw the last exception we got.
131 dl 1.7 ExecutionException ee = null;
132 dl 1.15 long lastTime = (timed)? System.nanoTime() : 0;
133 jsr166 1.26 Iterator<? extends Callable<T>> it = tasks.iterator();
134 dl 1.15
135     // Start one task for sure; the rest incrementally
136     futures.add(ecs.submit(it.next()));
137     --ntasks;
138     int active = 1;
139    
140     for (;;) {
141 jsr166 1.20 Future<T> f = ecs.poll();
142 dl 1.15 if (f == null) {
143     if (ntasks > 0) {
144     --ntasks;
145     futures.add(ecs.submit(it.next()));
146     ++active;
147     }
148 jsr166 1.20 else if (active == 0)
149 dl 1.15 break;
150     else if (timed) {
151     f = ecs.poll(nanos, TimeUnit.NANOSECONDS);
152     if (f == null)
153     throw new TimeoutException();
154     long now = System.nanoTime();
155     nanos -= now - lastTime;
156     lastTime = now;
157     }
158 jsr166 1.20 else
159 dl 1.15 f = ecs.take();
160     }
161     if (f != null) {
162     --active;
163     try {
164     return f.get();
165 jsr166 1.19 } catch (InterruptedException ie) {
166 dl 1.15 throw ie;
167 jsr166 1.19 } catch (ExecutionException eex) {
168 dl 1.15 ee = eex;
169 jsr166 1.19 } catch (RuntimeException rex) {
170 dl 1.15 ee = new ExecutionException(rex);
171     }
172 dl 1.7 }
173 jsr166 1.20 }
174 dl 1.15
175     if (ee == null)
176     ee = new ExecutionException();
177     throw ee;
178    
179 dl 1.3 } finally {
180 jsr166 1.20 for (Future<T> f : futures)
181 dl 1.4 f.cancel(true);
182 dl 1.3 }
183     }
184    
185 jsr166 1.26 public <T> T invokeAny(Collection<? extends Callable<T>> tasks)
186 dl 1.15 throws InterruptedException, ExecutionException {
187     try {
188     return doInvokeAny(tasks, false, 0);
189     } catch (TimeoutException cannotHappen) {
190     assert false;
191     return null;
192     }
193     }
194    
195 jsr166 1.26 public <T> T invokeAny(Collection<? extends Callable<T>> tasks,
196 jsr166 1.20 long timeout, TimeUnit unit)
197 dl 1.7 throws InterruptedException, ExecutionException, TimeoutException {
198 dl 1.15 return doInvokeAny(tasks, true, unit.toNanos(timeout));
199 dl 1.3 }
200    
201 jsr166 1.26 public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks)
202 dl 1.3 throws InterruptedException {
203     if (tasks == null)
204     throw new NullPointerException();
205 dl 1.6 List<Future<T>> futures = new ArrayList<Future<T>>(tasks.size());
206     boolean done = false;
207 dl 1.3 try {
208     for (Callable<T> t : tasks) {
209 peierls 1.21 RunnableFuture<T> f = newTaskFor(t);
210 dl 1.3 futures.add(f);
211     execute(f);
212     }
213 dl 1.6 for (Future<T> f : futures) {
214     if (!f.isDone()) {
215 jsr166 1.20 try {
216     f.get();
217 jsr166 1.19 } catch (CancellationException ignore) {
218     } catch (ExecutionException ignore) {
219 dl 1.6 }
220     }
221     }
222     done = true;
223 dl 1.3 return futures;
224     } finally {
225 dl 1.6 if (!done)
226 jsr166 1.20 for (Future<T> f : futures)
227 dl 1.4 f.cancel(true);
228 dl 1.3 }
229     }
230    
231 jsr166 1.26 public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks,
232 jsr166 1.20 long timeout, TimeUnit unit)
233 dl 1.3 throws InterruptedException {
234     if (tasks == null || unit == null)
235     throw new NullPointerException();
236     long nanos = unit.toNanos(timeout);
237 dl 1.6 List<Future<T>> futures = new ArrayList<Future<T>>(tasks.size());
238     boolean done = false;
239 dl 1.3 try {
240 jsr166 1.20 for (Callable<T> t : tasks)
241 peierls 1.21 futures.add(newTaskFor(t));
242 dl 1.16
243     long lastTime = System.nanoTime();
244    
245     // Interleave time checks and calls to execute in case
246     // executor doesn't have any/much parallelism.
247     Iterator<Future<T>> it = futures.iterator();
248     while (it.hasNext()) {
249     execute((Runnable)(it.next()));
250     long now = System.nanoTime();
251     nanos -= now - lastTime;
252     lastTime = now;
253     if (nanos <= 0)
254 jsr166 1.20 return futures;
255 dl 1.3 }
256 dl 1.16
257 dl 1.6 for (Future<T> f : futures) {
258     if (!f.isDone()) {
259 jsr166 1.20 if (nanos <= 0)
260     return futures;
261     try {
262     f.get(nanos, TimeUnit.NANOSECONDS);
263 jsr166 1.19 } catch (CancellationException ignore) {
264     } catch (ExecutionException ignore) {
265     } catch (TimeoutException toe) {
266 dl 1.6 return futures;
267     }
268 dl 1.8 long now = System.nanoTime();
269     nanos -= now - lastTime;
270     lastTime = now;
271 dl 1.6 }
272     }
273     done = true;
274 dl 1.3 return futures;
275     } finally {
276 dl 1.6 if (!done)
277 jsr166 1.20 for (Future<T> f : futures)
278 dl 1.4 f.cancel(true);
279 dl 1.3 }
280     }
281    
282 tim 1.1 }