ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/main/java/util/concurrent/AbstractExecutorService.java
Revision: 1.23
Committed: Fri May 20 16:25:51 2005 UTC (19 years ago) by dl
Branch: MAIN
Changes since 1.22: +3 -3 lines
Log Message:
fix syntax in sample code

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     * http://creativecommons.org/licenses/publicdomain
5 tim 1.1 */
6    
7     package java.util.concurrent;
8    
9 dl 1.3 import java.util.*;
10 tim 1.1
11     /**
12 dl 1.2 * Provides default implementation of {@link ExecutorService}
13 dl 1.12 * execution methods. This class implements the <tt>submit</tt>,
14 peierls 1.21 * <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 dl 1.18 * the implementation of <tt>submit(Runnable)</tt> creates an
18 peierls 1.21 * 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 tim 1.1 *
23 dl 1.22 * <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 dl 1.23 * static class CustomTask&lt;V&gt; implements RunnableFuture&lt;V&gt; {...}
30 dl 1.22 *
31 dl 1.23 * protected &lt;V&gt; RunnableFuture&lt;V&gt; newTaskFor(Callable&lt;V&gt; c) {
32 dl 1.22 * return new CustomTask&lt;V&gt;(c);
33     * }
34 dl 1.23 * protected &lt;V&gt; RunnableFuture&lt;V&gt; newTaskFor(Runnable r, V v) {
35 dl 1.22 * return new CustomTask&lt;V&gt;(r, v);
36     * }
37     * // ... add constructors, etc.
38     * }
39     * </pre>
40 tim 1.1 * @since 1.5
41     * @author Doug Lea
42     */
43     public abstract class AbstractExecutorService implements ExecutorService {
44    
45 peierls 1.21 /**
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 dl 1.22 * @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 peierls 1.21 */
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 dl 1.22 * @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 peierls 1.21 */
69     protected <T> RunnableFuture<T> newTaskFor(Callable<T> callable) {
70     return new FutureTask<T>(callable);
71     }
72    
73 dl 1.11 public Future<?> submit(Runnable task) {
74 dl 1.13 if (task == null) throw new NullPointerException();
75 peierls 1.21 RunnableFuture<Object> ftask = newTaskFor(task, null);
76 tim 1.1 execute(ftask);
77     return ftask;
78     }
79    
80 dl 1.13 public <T> Future<T> submit(Runnable task, T result) {
81     if (task == null) throw new NullPointerException();
82 peierls 1.21 RunnableFuture<T> ftask = newTaskFor(task, result);
83 dl 1.13 execute(ftask);
84     return ftask;
85     }
86    
87 tim 1.1 public <T> Future<T> submit(Callable<T> task) {
88 dl 1.13 if (task == null) throw new NullPointerException();
89 peierls 1.21 RunnableFuture<T> ftask = newTaskFor(task);
90 tim 1.1 execute(ftask);
91     return ftask;
92     }
93    
94 dl 1.15 /**
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 dl 1.3 if (tasks == null)
101     throw new NullPointerException();
102 dl 1.15 int ntasks = tasks.size();
103     if (ntasks == 0)
104 dl 1.7 throw new IllegalArgumentException();
105 dl 1.15 List<Future<T>> futures= new ArrayList<Future<T>>(ntasks);
106 jsr166 1.20 ExecutorCompletionService<T> ecs =
107 dl 1.7 new ExecutorCompletionService<T>(this);
108 dl 1.15
109     // For efficiency, especially in executors with limited
110     // parallelism, check to see if previously submitted tasks are
111 dl 1.18 // done before submitting more of them. This interleaving
112 dl 1.15 // plus the exception mechanics account for messiness of main
113 dl 1.18 // loop.
114 dl 1.15
115 dl 1.3 try {
116 dl 1.15 // Record exceptions so that if we fail to obtain any
117     // result, we can throw the last exception we got.
118 dl 1.7 ExecutionException ee = null;
119 dl 1.15 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 jsr166 1.20 Future<T> f = ecs.poll();
129 dl 1.15 if (f == null) {
130     if (ntasks > 0) {
131     --ntasks;
132     futures.add(ecs.submit(it.next()));
133     ++active;
134     }
135 jsr166 1.20 else if (active == 0)
136 dl 1.15 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 jsr166 1.20 else
146 dl 1.15 f = ecs.take();
147     }
148     if (f != null) {
149     --active;
150     try {
151     return f.get();
152 jsr166 1.19 } catch (InterruptedException ie) {
153 dl 1.15 throw ie;
154 jsr166 1.19 } catch (ExecutionException eex) {
155 dl 1.15 ee = eex;
156 jsr166 1.19 } catch (RuntimeException rex) {
157 dl 1.15 ee = new ExecutionException(rex);
158     }
159 dl 1.7 }
160 jsr166 1.20 }
161 dl 1.15
162     if (ee == null)
163     ee = new ExecutionException();
164     throw ee;
165    
166 dl 1.3 } finally {
167 jsr166 1.20 for (Future<T> f : futures)
168 dl 1.4 f.cancel(true);
169 dl 1.3 }
170     }
171    
172 dl 1.15 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 jsr166 1.20 public <T> T invokeAny(Collection<Callable<T>> tasks,
183     long timeout, TimeUnit unit)
184 dl 1.7 throws InterruptedException, ExecutionException, TimeoutException {
185 dl 1.15 return doInvokeAny(tasks, true, unit.toNanos(timeout));
186 dl 1.3 }
187    
188 dl 1.9 public <T> List<Future<T>> invokeAll(Collection<Callable<T>> tasks)
189 dl 1.3 throws InterruptedException {
190     if (tasks == null)
191     throw new NullPointerException();
192 dl 1.6 List<Future<T>> futures = new ArrayList<Future<T>>(tasks.size());
193     boolean done = false;
194 dl 1.3 try {
195     for (Callable<T> t : tasks) {
196 peierls 1.21 RunnableFuture<T> f = newTaskFor(t);
197 dl 1.3 futures.add(f);
198     execute(f);
199     }
200 dl 1.6 for (Future<T> f : futures) {
201     if (!f.isDone()) {
202 jsr166 1.20 try {
203     f.get();
204 jsr166 1.19 } catch (CancellationException ignore) {
205     } catch (ExecutionException ignore) {
206 dl 1.6 }
207     }
208     }
209     done = true;
210 dl 1.3 return futures;
211     } finally {
212 dl 1.6 if (!done)
213 jsr166 1.20 for (Future<T> f : futures)
214 dl 1.4 f.cancel(true);
215 dl 1.3 }
216     }
217    
218 jsr166 1.20 public <T> List<Future<T>> invokeAll(Collection<Callable<T>> tasks,
219     long timeout, TimeUnit unit)
220 dl 1.3 throws InterruptedException {
221     if (tasks == null || unit == null)
222     throw new NullPointerException();
223     long nanos = unit.toNanos(timeout);
224 dl 1.6 List<Future<T>> futures = new ArrayList<Future<T>>(tasks.size());
225     boolean done = false;
226 dl 1.3 try {
227 jsr166 1.20 for (Callable<T> t : tasks)
228 peierls 1.21 futures.add(newTaskFor(t));
229 dl 1.16
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 jsr166 1.20 return futures;
242 dl 1.3 }
243 dl 1.16
244 dl 1.6 for (Future<T> f : futures) {
245     if (!f.isDone()) {
246 jsr166 1.20 if (nanos <= 0)
247     return futures;
248     try {
249     f.get(nanos, TimeUnit.NANOSECONDS);
250 jsr166 1.19 } catch (CancellationException ignore) {
251     } catch (ExecutionException ignore) {
252     } catch (TimeoutException toe) {
253 dl 1.6 return futures;
254     }
255 dl 1.8 long now = System.nanoTime();
256     nanos -= now - lastTime;
257     lastTime = now;
258 dl 1.6 }
259     }
260     done = true;
261 dl 1.3 return futures;
262     } finally {
263 dl 1.6 if (!done)
264 jsr166 1.20 for (Future<T> f : futures)
265 dl 1.4 f.cancel(true);
266 dl 1.3 }
267     }
268    
269 tim 1.1 }