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

# Content
1 /*
2 * Written by Doug Lea with assistance from members of JCP JSR-166
3 * Expert Group and released to the public domain, as explained at
4 * http://creativecommons.org/licenses/publicdomain
5 */
6
7 package java.util.concurrent;
8 import java.util.*;
9
10 /**
11 * Provides default implementations of {@link ExecutorService}
12 * execution methods. This class implements the <tt>submit</tt>,
13 * <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 * the implementation of <tt>submit(Runnable)</tt> creates an
17 * associated <tt>RunnableFuture</tt> that is executed and
18 * returned. Subclasses may override the <tt>newTaskFor</tt> methods
19 * to return <tt>RunnableFuture</tt> implementations other than
20 * <tt>FutureTask</tt>.
21 *
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 * static class CustomTask&lt;V&gt; implements RunnableFuture&lt;V&gt; {...}
29 *
30 * 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 * }
38 * </pre>
39 * @since 1.5
40 * @author Doug Lea
41 */
42 public abstract class AbstractExecutorService implements ExecutorService {
43
44 /**
45 * Returns a <tt>RunnableFuture</tt> for the given runnable and default
46 * value.
47 *
48 * @param runnable the runnable task being wrapped
49 * @param value the default value for the returned future
50 * @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 */
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 *
63 * @param callable the callable task being wrapped
64 * @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 */
70 protected <T> RunnableFuture<T> newTaskFor(Callable<T> callable) {
71 return new FutureTask<T>(callable);
72 }
73
74 /**
75 * @throws RejectedExecutionException {@inheritDoc}
76 * @throws NullPointerException {@inheritDoc}
77 */
78 public Future<?> submit(Runnable task) {
79 if (task == null) throw new NullPointerException();
80 RunnableFuture<Object> ftask = newTaskFor(task, null);
81 execute(ftask);
82 return ftask;
83 }
84
85 /**
86 * @throws RejectedExecutionException {@inheritDoc}
87 * @throws NullPointerException {@inheritDoc}
88 */
89 public <T> Future<T> submit(Runnable task, T result) {
90 if (task == null) throw new NullPointerException();
91 RunnableFuture<T> ftask = newTaskFor(task, result);
92 execute(ftask);
93 return ftask;
94 }
95
96 /**
97 * @throws RejectedExecutionException {@inheritDoc}
98 * @throws NullPointerException {@inheritDoc}
99 */
100 public <T> Future<T> submit(Callable<T> task) {
101 if (task == null) throw new NullPointerException();
102 RunnableFuture<T> ftask = newTaskFor(task);
103 execute(ftask);
104 return ftask;
105 }
106
107 /**
108 * the main mechanics of invokeAny.
109 */
110 private <T> T doInvokeAny(Collection<? extends Callable<T>> tasks,
111 boolean timed, long nanos)
112 throws InterruptedException, ExecutionException, TimeoutException {
113 if (tasks == null)
114 throw new NullPointerException();
115 int ntasks = tasks.size();
116 if (ntasks == 0)
117 throw new IllegalArgumentException();
118 List<Future<T>> futures= new ArrayList<Future<T>>(ntasks);
119 ExecutorCompletionService<T> ecs =
120 new ExecutorCompletionService<T>(this);
121
122 // For efficiency, especially in executors with limited
123 // parallelism, check to see if previously submitted tasks are
124 // done before submitting more of them. This interleaving
125 // plus the exception mechanics account for messiness of main
126 // loop.
127
128 try {
129 // Record exceptions so that if we fail to obtain any
130 // result, we can throw the last exception we got.
131 ExecutionException ee = null;
132 long lastTime = (timed)? System.nanoTime() : 0;
133 Iterator<? extends Callable<T>> it = tasks.iterator();
134
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 Future<T> f = ecs.poll();
142 if (f == null) {
143 if (ntasks > 0) {
144 --ntasks;
145 futures.add(ecs.submit(it.next()));
146 ++active;
147 }
148 else if (active == 0)
149 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 else
159 f = ecs.take();
160 }
161 if (f != null) {
162 --active;
163 try {
164 return f.get();
165 } catch (InterruptedException ie) {
166 throw ie;
167 } catch (ExecutionException eex) {
168 ee = eex;
169 } catch (RuntimeException rex) {
170 ee = new ExecutionException(rex);
171 }
172 }
173 }
174
175 if (ee == null)
176 ee = new ExecutionException();
177 throw ee;
178
179 } finally {
180 for (Future<T> f : futures)
181 f.cancel(true);
182 }
183 }
184
185 public <T> T invokeAny(Collection<? extends Callable<T>> tasks)
186 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 public <T> T invokeAny(Collection<? extends Callable<T>> tasks,
196 long timeout, TimeUnit unit)
197 throws InterruptedException, ExecutionException, TimeoutException {
198 return doInvokeAny(tasks, true, unit.toNanos(timeout));
199 }
200
201 public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks)
202 throws InterruptedException {
203 if (tasks == null)
204 throw new NullPointerException();
205 List<Future<T>> futures = new ArrayList<Future<T>>(tasks.size());
206 boolean done = false;
207 try {
208 for (Callable<T> t : tasks) {
209 RunnableFuture<T> f = newTaskFor(t);
210 futures.add(f);
211 execute(f);
212 }
213 for (Future<T> f : futures) {
214 if (!f.isDone()) {
215 try {
216 f.get();
217 } catch (CancellationException ignore) {
218 } catch (ExecutionException ignore) {
219 }
220 }
221 }
222 done = true;
223 return futures;
224 } finally {
225 if (!done)
226 for (Future<T> f : futures)
227 f.cancel(true);
228 }
229 }
230
231 public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks,
232 long timeout, TimeUnit unit)
233 throws InterruptedException {
234 if (tasks == null || unit == null)
235 throw new NullPointerException();
236 long nanos = unit.toNanos(timeout);
237 List<Future<T>> futures = new ArrayList<Future<T>>(tasks.size());
238 boolean done = false;
239 try {
240 for (Callable<T> t : tasks)
241 futures.add(newTaskFor(t));
242
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 return futures;
255 }
256
257 for (Future<T> f : futures) {
258 if (!f.isDone()) {
259 if (nanos <= 0)
260 return futures;
261 try {
262 f.get(nanos, TimeUnit.NANOSECONDS);
263 } catch (CancellationException ignore) {
264 } catch (ExecutionException ignore) {
265 } catch (TimeoutException toe) {
266 return futures;
267 }
268 long now = System.nanoTime();
269 nanos -= now - lastTime;
270 lastTime = now;
271 }
272 }
273 done = true;
274 return futures;
275 } finally {
276 if (!done)
277 for (Future<T> f : futures)
278 f.cancel(true);
279 }
280 }
281
282 }