ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/main/java/util/concurrent/AbstractExecutorService.java
Revision: 1.47
Committed: Sun May 25 02:33:45 2014 UTC (10 years ago) by jsr166
Branch: MAIN
Changes since 1.46: +3 -3 lines
Log Message:
time to start using diamond <>

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