ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/main/java/util/concurrent/ExecutorCompletionService.java
Revision: 1.6
Committed: Fri Dec 19 14:42:25 2003 UTC (20 years, 5 months ago) by dl
Branch: MAIN
Changes since 1.5: +11 -14 lines
Log Message:
Documentation improvements

File Contents

# User Rev Content
1 dl 1.1 /*
2     * Written by Doug Lea with assistance from members of JCP JSR-166
3     * Expert Group and released to the public domain. Use, modify, and
4     * redistribute this code in any way without acknowledgement.
5     */
6    
7     package java.util.concurrent;
8    
9    
10     /**
11 jozart 1.2 * A {@link CompletionService} that uses a supplied {@link Executor}
12 dl 1.6 * to execute tasks.
13 dl 1.5 *
14     * <p>
15     *
16     * <b>Usage Examples.</b>
17 dl 1.6 * Suppose you have a set of solvers for a certain problem (each returning
18     * a value of some type <tt>Result</tt>),
19 dl 1.5 * and would like to run them concurrently, using the results of each of them
20     * that return a non-null value. You could write this as:
21     *
22     * <pre>
23 dl 1.6 * void solve(Executor e, Collection&lt;Callable&lt;Result&gt;&gt; solvers)
24     * throws InterruptedException, ExecutionException {
25     * CompletionService&lt;Result&gt; ecs = new ExecutorCompletionService&lt;Result&gt;(e);
26 dl 1.5 * for (Callable&lt;Result&gt; s : solvers)
27     * ecs.submit(s);
28     * int n = solvers.size();
29     * for (int i = 0; i &lt; n; ++i) {
30     * Result r = ecs.take().get();
31     * if (r != null)
32     * use(r);
33     * }
34     * }
35     * </pre>
36     *
37     * Suppose instead that you would like to use the first non-null result
38 dl 1.6 * of the set of tasks, ignoring any of those that encounter exceptions,
39     * and cancelling all other tasks when the first one is ready:
40 dl 1.5 *
41     * <pre>
42     * void solve(Executor e, Collection&lt;Callable&lt;Result&gt;&gt; solvers)
43 dl 1.6 * throws InterruptedException {
44     * CompletionService&lt;Result&gt; ecs = new ExecutorCompletionService&lt;Result&gt;(e);
45 dl 1.5 * int n = solvers.size();
46 dl 1.6 * List&lt;Future&lt;Result&gt;&gt; futures = new ArrayList&lt;Future&lt;Result&gt;&gt;(n);
47 dl 1.5 * Result result = null;
48     * try {
49     * for (Callable&lt;Result&gt; s : solvers)
50     * futures.add(ecs.submit(s));
51     * for (int i = 0; i &lt; n; ++i) {
52     * try {
53     * Result r = ecs.take().get();
54     * if (r != null) {
55     * result = r;
56     * break;
57     * }
58     * } catch(ExecutionException ignore) {}
59     * }
60     * }
61     * finally {
62     * for (Future&lt;Result&gt; f : futures)
63     * f.cancel(true);
64     * }
65     *
66     * if (result != null)
67     * use(result);
68     * }
69     * </pre>
70 dl 1.1 */
71     public class ExecutorCompletionService<V> implements CompletionService<V> {
72 jozart 1.2 private final Executor executor;
73 dl 1.3 private final BlockingQueue<Future<V>> completionQueue;
74 dl 1.1
75     /**
76     * FutureTask extension to enqueue upon completion
77     */
78 dl 1.4 private class QueueingFuture extends FutureTask<V> {
79     QueueingFuture(Callable<V> c) { super(c); }
80     QueueingFuture(Runnable t, V r) { super(t, r); }
81     protected void done() { completionQueue.add(this); }
82 dl 1.1 }
83    
84     /**
85     * Creates an ExecutorCompletionService using the supplied
86 dl 1.3 * executor for base task execution and a
87     * {@link LinkedBlockingQueue} as a completion queue.
88 dl 1.5 * @param executor the executor to use
89 dl 1.3 8 @throws NullPointerException if executor is <tt>null</tt>
90 dl 1.1 */
91 jozart 1.2 public ExecutorCompletionService(Executor executor) {
92 dl 1.1 if (executor == null)
93     throw new NullPointerException();
94     this.executor = executor;
95 dl 1.3 this.completionQueue = new LinkedBlockingQueue<Future<V>>();
96 dl 1.1 }
97    
98     /**
99 dl 1.3 * Creates an ExecutorCompletionService using the supplied
100     * executor for base task execution and the supplied queue as its
101     * completion queue.
102 dl 1.5 * @param executor the executor to use
103 dl 1.3 * @param completionQueue the queue to use as the completion queue;
104     * normally one dedicated for use by this service
105     8 @throws NullPointerException if executor or completionQueue are <tt>null</tt>
106 dl 1.1 */
107 dl 1.3 public ExecutorCompletionService(Executor executor,
108     BlockingQueue<Future<V>> completionQueue) {
109     if (executor == null || completionQueue == null)
110     throw new NullPointerException();
111     this.executor = executor;
112     this.completionQueue = completionQueue;
113 dl 1.1 }
114    
115     public Future<V> submit(Callable<V> task) {
116 dl 1.4 QueueingFuture f = new QueueingFuture(task);
117 dl 1.1 executor.execute(f);
118     return f;
119     }
120    
121     public Future<V> submit(Runnable task, V result) {
122 dl 1.4 QueueingFuture f = new QueueingFuture(task, result);
123 dl 1.1 executor.execute(f);
124     return f;
125     }
126    
127     public Future<V> take() throws InterruptedException {
128 dl 1.3 return completionQueue.take();
129 dl 1.1 }
130    
131     public Future<V> poll() {
132 dl 1.3 return completionQueue.poll();
133 dl 1.1 }
134    
135     public Future<V> poll(long timeout, TimeUnit unit) throws InterruptedException {
136 dl 1.3 return completionQueue.poll(timeout, unit);
137 dl 1.1 }
138 dl 1.5
139 dl 1.1 }
140    
141