public class Promise<T> extends Object
public T findSomething(Args args);
then this method should be represented in promise-oriented way like this:
public Promise<T> findSomethingPromise(Args args);
In this case, the call to findSomething(args) is semantically equivalent to
findSomethingPromise(args).. There may be service-specific difference between
those two forms of invocation. If await()findSomething throws exception, then await
wraps them into PromiseException. If findSomething consults some kind of local cache with subscription,
then it may be defined by the service to return immediately and only retrieve the result from the cache, while
findSomethingPromise is a proper form that makes potentially time-consuming call to a back end data provider.
findSomethingPromise via findSomething using an Executor for
background computation looks like this:
public Promise<T> findSomethingPromise(Args args) {
Promise<T> promise = new Promise<T>();
executor.execute(() -> {
try {
T result = findSomething(args);
promise.complete(result);
} catch (Throwable t) {
promise.completeExceptionally(t);
}
});
return promise;
}
A more advanced implementation may also cancel pending and/or ongoing computation when client cancels the promise or
times out waiting for a promise to be completed.
The sketch of such implementation using an ExecutorService is:
public Promise<T> findSomethingPromise(Args args) {
Promise<T> promise = new Promise<T>();
Future<?> future = executor.submit(() -> {
try {
T result = findSomething(args);
promise.complete(result);
} catch (Throwable t) {
promise.completeExceptionally(t);
}
});
promise.whenDone(p -> future.cancel(true)); // true to interrupt running task
return promise;
}
try {
findSomething(args).await();
handleResult(result);
} catch (Throwable t) {
handleException(t);
}
Waiting with timeout is performed by replacing await call with await(timeout, unit).
The same handling can be performed in the service provider thread like this:
findSomething(args).whenDone(promise -> {
if (promise.hasResult())
handleResult(promise.getResult());
else
handleException(promise.getException());
});
| What \ State | Initial | Result | Exception | Cancelled |
|---|---|---|---|---|
| Transition method | constructor |
complete |
completeExceptionally |
cancel |
isDone |
false |
true |
true |
true |
hasResult |
false |
true |
false |
false |
hasException |
false |
false |
true |
true |
isCancelled |
false |
false |
false |
true |
getResult |
null |
result |
null |
null |
getException |
null |
null |
exception |
CancellationException |
By default, whenDone notifications are performed in the same thread that
invoked the state-changing method like complete,
completeExceptionally, or cancel.
Promise class can be extended to override protected handleDone
method to move notification to other threads, for example, or to do other kind of processing.
PromiseHandler, while at the same time
supporting multiple invocations of whenDone at the cost of extra
memory consumption. Performance-sensitive service implementations that need to cancel their internal computation
on the promise cancel are encouraged to extend Promise class and override handleDone for
this purpose instead of using whenDone.
Promises class for utility methods that combine multiple Promise instances to
facilitate batch processing and concurrent invocations.
Future and CompletableFuture. However, the methods
in this class are carefully selected to minimize the interface weight and the preference is given to methods
that do no throw checked exceptions. All the names of the methods are picked to avoid conflicts with
CompletionStage, so this class can be potentially enhanced to implement CompletionStage
while maintaining backwards compatibility.| Constructor and Description |
|---|
Promise()
Creates promise in the initial state and without an executor for notifications.
|
| Modifier and Type | Method and Description |
|---|---|
T |
await()
Wait for computation to complete and return its result or throw an exception in case of exceptional completion.
|
T |
await(long timeout,
TimeUnit unit)
Wait for computation to complete or timeout and return its result or throw an exception in case of exceptional completion or timeout.
|
boolean |
awaitWithoutException(long timeout,
TimeUnit unit)
Wait for computation to complete or timeout or throw an exception in case of exceptional completion.
|
void |
cancel()
Cancels computation.
|
void |
complete(T result)
Completes computation normally with a specified result.
|
static <T> Promise<T> |
completed(T result)
Returns new promise that is
completed with a specified result. |
void |
completeExceptionally(Throwable exception)
Completes computation exceptionally with a specified exception.
|
static <T> Promise<T> |
failed(Throwable exception)
Returns new promise that is
completed exceptionally with a
specified exception. |
Throwable |
getException()
Returns exceptional outcome of computation.
|
T |
getResult()
Returns result of computation.
|
protected void |
handleDone(PromiseHandler<? super T> handler)
Invoked when promise is done.
|
boolean |
hasException()
Returns
true when computation has completed exceptionally or was cancelled. |
boolean |
hasResult()
Returns
true when computation has completed normally. |
boolean |
isCancelled()
Returns
true when computation was cancelled. |
boolean |
isDone()
|
void |
whenDone(PromiseHandler<? super T> handler)
Registers a handler to be invoked exactly once when computation
completes. |
void |
whenDoneAsync(PromiseHandler<? super T> handler,
Executor executor)
Registers a handler to be invoked asynchronously exactly once when computation
completes. |
public Promise()
public final boolean isDone()
true when computation has completed.public final boolean hasResult()
true when computation has completed normally.
Use getResult() method to get the result of the computation.true when computation has completed normally.getResult()public final boolean hasException()
true when computation has completed exceptionally or was cancelled.
Use getException() method to get the exceptional outcome of the computation.true when computation has completed exceptionally or was cancelled.public final boolean isCancelled()
true when computation was cancelled.
Use getException() method to get the corresponding CancellationException.true when computation was cancelled.cancel(),
getException()public final T getResult()
result, then
this method returns null.hasResult()public final Throwable getException()
exception,
then this method returns null. If computation has completed exceptionally or was cancelled, then
the result of this method is not null.
If computation was cancelled, then this method returns an
instance of CancellationException.hasException()public final T await()
interrupted, then the computation is cancelled,
the interruption flag on the current thread is set, and CancellationException is thrown.
This method waits forever. See await(timeout, unit) for a timed wait
when the result of this promise is required to proceed or
awaitWithoutException(timeout, unit) when the result
is not required and the normal execution shall continue on timeout.
CancellationException - if computation was cancelled.PromiseException - if computation has completed exceptionally.public final T await(long timeout, TimeUnit unit)
interrupted, then the computation is cancelled,
the interruption flag on the current thread is set, and CancellationException is thrown.
If the wait times out, then the computation is cancelled and CancellationException is thrown.
Use this method in the code that must get and process the result of this promise, which is returned
by this method when it completes normally. When the result is not required and the normal execution shall
continue on timeout use awaitWithoutException.
CancellationException - if computation was cancelled or timed out.PromiseException - if computation has completed exceptionally.public final boolean awaitWithoutException(long timeout,
TimeUnit unit)
interrupted, then the computation is cancelled,
the interruption flag on the current thread is set, and CancellationException is thrown.
If the wait times out, then the computation is cancelled and this method returns false.
Use this method in the code that shall continue normal execution in case of timeout.
true if the computation has completed normally; false when wait timed out.CancellationException - if computation was cancelled.PromiseException - if computation has completed exceptionally.public final void cancel()
completed.
If cancelled, then getException will return CancellationException,
isDone, isCancelled, and hasException will return true,
all handlers that were installed with whenDone method
are notified by
invoking their promiseDone method, and
all waiters on join method throw CancellationException.
public final void complete(T result)
completed
(normally, exceptionally, or was cancelled),
If completed, then getResult will return the specified result,
isDone and hasResult will return true,
all handlers that were installed with whenDone method
are notified by invoking their promiseDone method, and
all waiters on join method return the result.
result - the result of computation.getResult()public final void completeExceptionally(Throwable exception)
completed,
otherwise getException() will return the specified exception.
If completed exceptionally, then getException will return the specified exception,
isDone and hasException will return true,
all handlers that were installed with whenDone method
are notified by invoking their promiseDone method, and
all waiters on join method throw PromiseException wrapping this exception.
exception - the exception.NullPointerException - if exception is null.getException()public final void whenDone(PromiseHandler<? super T> handler)
completes.
The handler's promiseDone method
is invoked immediately when this computation has already completed,
otherwise it will be invoked synchronously in the future when computation
completes normally,
or exceptionally,
or is cancelled from the same thread that had invoked one of the completion methods.
Exceptions that are produced by the invocation of
PromiseHandler.promiseDone method
are caught and logged.handler - the handler.NullPointerException - if handler is null.public final void whenDoneAsync(PromiseHandler<? super T> handler, Executor executor)
completes.
This method is a shortcut for the following code:
whenDone(new PromiseHandler<T>() {
public void promiseDone(Promise<? extends T> promise) {
executor.execute(new Runnable() {
public void run() {
handler.promiseDone(Promise.this);
}
});
}
});
handler - the handler.executor - the executor.NullPointerException - if handler or executor is null.public static <T> Promise<T> completed(T result)
completed with a specified result.T - the result type.result - the result of computation.completed with a specified result.public static <T> Promise<T> failed(Throwable exception)
completed exceptionally with a
specified exception.T - the result type.exception - the exception.completed exceptionally with a
specified exception.NullPointerException - if exception is null.protected void handleDone(PromiseHandler<? super T> handler)
PromiseHandler.promiseDone on all handlers.handler - reference to installed handlers list or null when no handlers were set.Copyright © 2002–2023 Devexperts LLC. All rights reserved.