ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/jdk8/java/util/concurrent/AbstractExecutorService.java
Revision: 1.1
Committed: Sat Mar 26 06:22:49 2016 UTC (8 years, 2 months ago) by jsr166
Branch: MAIN
CVS Tags: HEAD
Log Message:
fork jdk8 maintenance branch for source and jtreg tests

File Contents

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