132 |
|
*/ |
133 |
|
V get(long timeout, TimeUnit unit) |
134 |
|
throws InterruptedException, ExecutionException, TimeoutException; |
135 |
+ |
|
136 |
+ |
/** |
137 |
+ |
* Returns the computed result, without waiting. |
138 |
+ |
* |
139 |
+ |
* <p> This method is for cases where the caller knows that the task has |
140 |
+ |
* already completed successfully, for example a filter-map of a stream of |
141 |
+ |
* Future objects where the filter matches tasks that completed successfully. |
142 |
+ |
* {@snippet lang=java : |
143 |
+ |
* results = futures.stream() |
144 |
+ |
* .filter(f -> f.state() == Future.State.SUCCESS) |
145 |
+ |
* .map(Future::resultNow) |
146 |
+ |
* .toList(); |
147 |
+ |
* } |
148 |
+ |
* |
149 |
+ |
* @implSpec |
150 |
+ |
* The default implementation invokes {@code isDone()} to test if the task |
151 |
+ |
* has completed. If done, it invokes {@code get()} to obtain the result. |
152 |
+ |
* |
153 |
+ |
* @return the computed result |
154 |
+ |
* @throws IllegalStateException if the task has not completed or the task |
155 |
+ |
* did not complete with a result |
156 |
+ |
* @since 99 |
157 |
+ |
*/ |
158 |
+ |
default V resultNow() { |
159 |
+ |
if (!isDone()) |
160 |
+ |
throw new IllegalStateException("Task has not completed"); |
161 |
+ |
boolean interrupted = false; |
162 |
+ |
try { |
163 |
+ |
while (true) { |
164 |
+ |
try { |
165 |
+ |
return get(); |
166 |
+ |
} catch (InterruptedException e) { |
167 |
+ |
interrupted = true; |
168 |
+ |
} catch (ExecutionException e) { |
169 |
+ |
throw new IllegalStateException("Task completed with exception"); |
170 |
+ |
} catch (CancellationException e) { |
171 |
+ |
throw new IllegalStateException("Task was cancelled"); |
172 |
+ |
} |
173 |
+ |
} |
174 |
+ |
} finally { |
175 |
+ |
if (interrupted) Thread.currentThread().interrupt(); |
176 |
+ |
} |
177 |
+ |
} |
178 |
+ |
|
179 |
+ |
/** |
180 |
+ |
* Returns the exception thrown by the task, without waiting. |
181 |
+ |
* |
182 |
+ |
* <p> This method is for cases where the caller knows that the task |
183 |
+ |
* has already completed with an exception. |
184 |
+ |
* |
185 |
+ |
* @implSpec |
186 |
+ |
* The default implementation invokes {@code isDone()} to test if the task |
187 |
+ |
* has completed. If done and not cancelled, it invokes {@code get()} and |
188 |
+ |
* catches the {@code ExecutionException} to obtain the exception. |
189 |
+ |
* |
190 |
+ |
* @return the exception thrown by the task |
191 |
+ |
* @throws IllegalStateException if the task has not completed, the task |
192 |
+ |
* completed normally, or the task was cancelled |
193 |
+ |
* @since 99 |
194 |
+ |
*/ |
195 |
+ |
default Throwable exceptionNow() { |
196 |
+ |
if (!isDone()) |
197 |
+ |
throw new IllegalStateException("Task has not completed"); |
198 |
+ |
if (isCancelled()) |
199 |
+ |
throw new IllegalStateException("Task was cancelled"); |
200 |
+ |
boolean interrupted = false; |
201 |
+ |
try { |
202 |
+ |
while (true) { |
203 |
+ |
try { |
204 |
+ |
get(); |
205 |
+ |
throw new IllegalStateException("Task completed with a result"); |
206 |
+ |
} catch (InterruptedException e) { |
207 |
+ |
interrupted = true; |
208 |
+ |
} catch (ExecutionException e) { |
209 |
+ |
return e.getCause(); |
210 |
+ |
} |
211 |
+ |
} |
212 |
+ |
} finally { |
213 |
+ |
if (interrupted) Thread.currentThread().interrupt(); |
214 |
+ |
} |
215 |
+ |
} |
216 |
+ |
|
217 |
+ |
/** |
218 |
+ |
* Represents the computation state. |
219 |
+ |
* @since 99 |
220 |
+ |
*/ |
221 |
+ |
enum State { |
222 |
+ |
/** |
223 |
+ |
* The task has not completed. |
224 |
+ |
*/ |
225 |
+ |
RUNNING, |
226 |
+ |
/** |
227 |
+ |
* The task completed with a result. |
228 |
+ |
* @see Future#resultNow() |
229 |
+ |
*/ |
230 |
+ |
SUCCESS, |
231 |
+ |
/** |
232 |
+ |
* The task completed with an exception. |
233 |
+ |
* @see Future#exceptionNow() |
234 |
+ |
*/ |
235 |
+ |
FAILED, |
236 |
+ |
/** |
237 |
+ |
* The task was cancelled. |
238 |
+ |
* @see #cancel(boolean) |
239 |
+ |
*/ |
240 |
+ |
CANCELLED |
241 |
+ |
} |
242 |
+ |
|
243 |
+ |
/** |
244 |
+ |
* {@return the computation state} |
245 |
+ |
* |
246 |
+ |
* @implSpec |
247 |
+ |
* The default implementation uses {@code isDone()}, {@code isCancelled()}, |
248 |
+ |
* and {@code get()} to determine the state. |
249 |
+ |
* |
250 |
+ |
* @since 99 |
251 |
+ |
*/ |
252 |
+ |
default State state() { |
253 |
+ |
if (!isDone()) |
254 |
+ |
return State.RUNNING; |
255 |
+ |
if (isCancelled()) |
256 |
+ |
return State.CANCELLED; |
257 |
+ |
boolean interrupted = false; |
258 |
+ |
try { |
259 |
+ |
while (true) { |
260 |
+ |
try { |
261 |
+ |
get(); // may throw InterruptedException when done |
262 |
+ |
return State.SUCCESS; |
263 |
+ |
} catch (InterruptedException e) { |
264 |
+ |
interrupted = true; |
265 |
+ |
} catch (ExecutionException e) { |
266 |
+ |
return State.FAILED; |
267 |
+ |
} |
268 |
+ |
} |
269 |
+ |
} finally { |
270 |
+ |
if (interrupted) Thread.currentThread().interrupt(); |
271 |
+ |
} |
272 |
+ |
} |
273 |
|
} |
274 |
+ |
|