ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/main/java/util/concurrent/FutureTask.java
Revision: 1.1
Committed: Wed May 14 21:30:47 2003 UTC (21 years, 1 month ago) by tim
Branch: MAIN
Log Message:
Moved main source rooted at . to ./src/main
Moved test source rooted at ./etc/testcases to ./src/test

File Contents

# Content
1 /*
2 * @(#)FutureTask.java
3 */
4
5 package java.util.concurrent;
6
7 /**
8 * A cancellable asynchronous computation.
9 *
10 * <p>Provides methods to start and cancel the computation, query to see if
11 * the computation is complete, and retrieve the result of the computation.
12 * The result can only be retrieved when the computation has completed;
13 * the <tt>get</tt> method will block if the computation has not yet completed.
14 * Once the computation is completed, the result cannot be changed, nor can the
15 * computation be restarted or cancelled.
16 *
17 * <p>Because <tt>FutureTask</tt> implements <tt>Runnable</tt>, a
18 * <tt>FutureTask</tt> can be submitted to an {@link Executor} for
19 * current or deferred execution.
20 *
21 * <p>A <tt>FutureTask</tt> can be used to wrap a <tt>Callable</tt> or
22 * <tt>Runnable</tt> object so that it can be scheduled for execution in a
23 * thread or an <tt>Executor</tt>, cancel
24 * computation before the computation completes, and wait for or
25 * retrieve the results. If the computation threw an exception, the
26 * exception is propagated to any thread that attempts to retrieve the
27 * result.
28 *
29 * @see Executor
30 *
31 * @since 1.5
32 * @spec JSR-166
33 * @revised $Date: 2003/03/31 03:50:08 $
34 * @editor $Author: dholmes $
35 */
36 public class FutureTask<V> implements Cancellable, Future<V>, Runnable {
37
38 private V result;
39 private Throwable exception;
40 private boolean ready;
41 private Thread runner;
42 private final Callable<V> callable;
43 private boolean cancelled;
44
45 /**
46 * Constructs a <tt>FutureTask</tt> that will upon running, execute the
47 * given <tt>Callable</tt>.
48 *
49 * @param callable the callable task
50 */
51 public FutureTask(Callable<V> callable) {
52 this.callable = callable;
53 }
54
55 /**
56 * Constructs a <tt>FutureTask</tt> that will upon running, execute the
57 * given <tt>Runnable</tt>, and arrange that <tt>get</tt> will return the
58 * given result on successful completion.
59 *
60 * @param runnable the runnable task
61 * @param result the result to return on successful completion. If
62 * you don't need a particular result, consider just using
63 * <tt>Boolean.TRUE</tt>.
64 */
65 public FutureTask(final Runnable runnable, final V result) {
66 callable = new Callable<V>() {
67 public V call() {
68 runnable.run();
69 return result;
70 }
71 };
72 }
73
74 /* Runnable implementation. */
75
76 /** Starts the computation. */
77 public void run() {
78 doRun();
79 }
80
81 /**
82 * Executes the callable if not already cancelled or running, and
83 * sets the value or exception with its results.
84 */
85 protected void doRun() {
86 try {
87 synchronized(this) {
88 if (ready || runner != null)
89 return;
90 runner = Thread.currentThread();
91 }
92 set(callable.call());
93 }
94 catch(Throwable ex) {
95 setException(ex);
96 }
97 }
98
99 /* Future implementation. INHERIT this javadoc from interface??? Note CancellationException. */
100
101 /**
102 * Waits if necessary for the computation to complete, and then retrieves
103 * its result.
104 *
105 * @return the computed result
106 * @throws CancellationException if task producing this value was
107 * cancelled before completion
108 * @throws ExecutionException if the underlying computation threw an exception
109 * @throws InterruptedException if current thread was interrupted while waiting
110 */
111 public synchronized V get() throws InterruptedException, ExecutionException {
112 while (!ready)
113 wait();
114 if (cancelled)
115 throw new CancellationException();
116 else if (exception != null)
117 throw new ExecutionException(exception);
118 else
119 return result;
120 }
121
122 /**
123 * Waits if necessary for at most the given time for the computation to
124 * complete, and then retrieves its result.
125 *
126 * @param timeout the maximum time to wait
127 * @param granularity the time unit of the timeout argument
128 * @return value of this task
129 * @throws CancellationException if task producing this value was cancelled before completion
130 * @throws ExecutionException if the underlying computation
131 * threw an exception.
132 * @throws InterruptedException if current thread was interrupted while waiting
133 * @throws TimeoutException if the wait timed out
134 */
135 public synchronized V get(long timeout, TimeUnit granularity)
136 throws InterruptedException, ExecutionException, TimeoutException {
137
138 if (!ready) {
139 long startTime = TimeUnit.highResolutionTime();
140 long waitTime = timeout;
141 for (;;) {
142 granularity.timedWait(this, waitTime);
143 if (ready)
144 break;
145 else {
146 waitTime = TimeUnit.highResolutionTime() - startTime;
147 if (waitTime <= 0)
148 throw new TimeoutException();
149 }
150 }
151 }
152 if (cancelled)
153 throw new CancellationException();
154 else if (exception != null)
155 throw new ExecutionException(exception);
156 else
157 return result;
158 }
159
160 /**
161 * Sets the value of this task to the given value. This method
162 * should only be called once; once it is called, the computation
163 * is assumed to have completed.
164 *
165 * @param v the value
166 *
167 * @fixme Need to clarify "should" in "should only be called once".
168 */
169 protected synchronized void set(V v) {
170 ready = true;
171 result = v;
172 runner = null;
173 notifyAll();
174 }
175
176 /**
177 * Indicates that the computation has failed. After this method
178 * is called, the computation is assumed to be completed, and any
179 * attempt to retrieve the result will throw an <tt>ExecutionException</tt>
180 * wrapping the exception provided here.
181 *
182 * @param t the throwable
183 */
184 protected synchronized void setException(Throwable t) {
185 ready = true;
186 exception = t;
187 runner = null;
188 notifyAll();
189 }
190
191 /* Cancellable implementation. */
192
193 public synchronized boolean cancel(boolean mayInterruptIfRunning) {
194 if (ready || cancelled)
195 return false;
196 if (mayInterruptIfRunning &&
197 runner != null && runner != Thread.currentThread())
198 runner.interrupt();
199 return cancelled = ready = true;
200 }
201
202 public synchronized boolean isCancelled() {
203 return cancelled;
204 }
205
206 public synchronized boolean isDone() {
207 return ready;
208 }
209 }
210
211
212
213
214
215
216
217
218
219