ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/main/java/util/concurrent/AbstractExecutorService.java
Revision: 1.49
Committed: Wed Dec 3 23:53:45 2014 UTC (9 years, 6 months ago) by jsr166
Branch: MAIN
Changes since 1.48: +37 -37 lines
Log Message:
improve implementation of invokeAll

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