ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/main/java/util/concurrent/AbstractExecutorService.java
Revision: 1.22
Committed: Tue May 17 13:08:08 2005 UTC (19 years ago) by dl
Branch: MAIN
Changes since 1.21: +27 -6 lines
Log Message:
Add documentation; adjust STPE internal types

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