9 |
|
|
10 |
|
/** |
11 |
|
* A {@link CompletionService} that uses a supplied {@link Executor} |
12 |
< |
* to execute tasks. |
12 |
> |
* to execute tasks. An <tt>ExecutorCompletionService</tt> can be |
13 |
> |
* useful as an add-on to solve task coordination problems. |
14 |
> |
* |
15 |
> |
* <p> |
16 |
> |
* |
17 |
> |
* <b>Usage Examples.</b> |
18 |
> |
* Suppose you have a set of solvers for a certain problem, |
19 |
> |
* 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 |
> |
* void solve(Executor e, Collection<Callable<Result>> solvers) |
24 |
> |
* throws InterruptedException, ExecutionException { |
25 |
> |
* ExecutorCompletionService<Result> ecs = new |
26 |
> |
* ExecutorCompletionService<Result>(e); |
27 |
> |
* for (Callable<Result> s : solvers) |
28 |
> |
* ecs.submit(s); |
29 |
> |
* int n = solvers.size(); |
30 |
> |
* for (int i = 0; i < n; ++i) { |
31 |
> |
* Result r = ecs.take().get(); |
32 |
> |
* if (r != null) |
33 |
> |
* use(r); |
34 |
> |
* } |
35 |
> |
* } |
36 |
> |
* </pre> |
37 |
> |
* |
38 |
> |
* Suppose instead that you would like to use the first non-null result |
39 |
> |
* of a set of tasks, ignoring any of those that encounter exceptions |
40 |
> |
* and cancelling all of the other tasks when the first one is ready: |
41 |
> |
* |
42 |
> |
* <pre> |
43 |
> |
* void solve(Executor e, Collection<Callable<Result>> solvers) |
44 |
> |
* throws InterruptedException { |
45 |
> |
* ExecutorCompletionService<Result> ecs = |
46 |
> |
* new ExecutorCompletionService<Result>(e); |
47 |
> |
* int n = solvers.size(); |
48 |
> |
* ArrayList<Future<Result>> futures = |
49 |
> |
* new ArrayList<Future<Result>>(n); |
50 |
> |
* Result result = null; |
51 |
> |
* try { |
52 |
> |
* for (Callable<Result> s : solvers) |
53 |
> |
* futures.add(ecs.submit(s)); |
54 |
> |
* for (int i = 0; i < n; ++i) { |
55 |
> |
* try { |
56 |
> |
* Result r = ecs.take().get(); |
57 |
> |
* if (r != null) { |
58 |
> |
* result = r; |
59 |
> |
* break; |
60 |
> |
* } |
61 |
> |
* } catch(ExecutionException ignore) {} |
62 |
> |
* } |
63 |
> |
* } |
64 |
> |
* finally { |
65 |
> |
* for (Future<Result> f : futures) |
66 |
> |
* f.cancel(true); |
67 |
> |
* } |
68 |
> |
* |
69 |
> |
* if (result != null) |
70 |
> |
* use(result); |
71 |
> |
* } |
72 |
> |
* </pre> |
73 |
|
*/ |
74 |
|
public class ExecutorCompletionService<V> implements CompletionService<V> { |
75 |
|
private final Executor executor; |
88 |
|
* Creates an ExecutorCompletionService using the supplied |
89 |
|
* executor for base task execution and a |
90 |
|
* {@link LinkedBlockingQueue} as a completion queue. |
91 |
< |
* @param executor the executor to use; normally |
32 |
< |
* one dedicated for use by this service |
91 |
> |
* @param executor the executor to use |
92 |
|
8 @throws NullPointerException if executor is <tt>null</tt> |
93 |
|
*/ |
94 |
|
public ExecutorCompletionService(Executor executor) { |
102 |
|
* Creates an ExecutorCompletionService using the supplied |
103 |
|
* executor for base task execution and the supplied queue as its |
104 |
|
* completion queue. |
105 |
< |
* @param executor the executor to use; normally |
47 |
< |
* one dedicated for use by this service |
105 |
> |
* @param executor the executor to use |
106 |
|
* @param completionQueue the queue to use as the completion queue; |
107 |
|
* normally one dedicated for use by this service |
108 |
|
8 @throws NullPointerException if executor or completionQueue are <tt>null</tt> |
138 |
|
public Future<V> poll(long timeout, TimeUnit unit) throws InterruptedException { |
139 |
|
return completionQueue.poll(timeout, unit); |
140 |
|
} |
141 |
+ |
|
142 |
|
} |
143 |
|
|
144 |
|
|