Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
*
* @since 1.0.0
*/
public class FutureUtils extends InternalFutureUtils {
/**
* This call blocks till all futures in the list have completed. If the future completed with
* an error, the {@link ExecutionException} is swallowed. Meaning that this does not attempt to
* verify that all futures completed successfully. If you need to know if any failed, please
* use {@link #blockTillAllCompleteOrFirstError(Iterable)}.
*
* If you need to specify a timeout to control how long to block, consider using
* {@link #blockTillAllComplete(Iterable, long)}.
*
* @param futures Futures to block till they complete
* @throws InterruptedException Thrown if thread is interrupted while waiting on future
*/
public static void blockTillAllComplete(Future> ... futures) throws InterruptedException {
countFuturesWithResult(ArrayIterator.makeIterable(futures), null);
}
/**
* This call blocks till all futures in the list have completed. If the future completed with
* an error, the {@link ExecutionException} is swallowed. Meaning that this does not attempt to
* verify that all futures completed successfully. If you need to know if any failed, please
* use {@link #blockTillAllCompleteOrFirstError(Iterable)}.
*
* If you need to specify a timeout to control how long to block, consider using
* {@link #blockTillAllComplete(Iterable, long)}.
*
* @param futures Structure of futures to iterate over
* @throws InterruptedException Thrown if thread is interrupted while waiting on future
*/
public static void blockTillAllComplete(Iterable extends Future>> futures) throws InterruptedException {
countFuturesWithResult(futures, null);
}
/**
* This call blocks till all futures in the list have completed. If the future completed with
* an error, the {@link ExecutionException} is swallowed. Meaning that this does not attempt to
* verify that all futures completed successfully. If you need to know if any failed, please
* use {@link #blockTillAllCompleteOrFirstError(Iterable, long)}.
*
* @since 4.0.0
* @param futures Structure of futures to iterate over
* @param timeoutInMillis timeout to wait for futures to complete in milliseconds
* @throws InterruptedException Thrown if thread is interrupted while waiting on future
* @throws TimeoutException Thrown if the timeout elapsed while waiting on futures to complete
*/
public static void blockTillAllComplete(Iterable extends Future>> futures, long timeoutInMillis)
throws InterruptedException, TimeoutException {
countFuturesWithResult(futures, null, timeoutInMillis);
}
/**
* This call blocks till all futures in the list have completed. If the future completed with
* an error an {@link ExecutionException} is thrown. If this exception is thrown, all futures
* may or may not be completed, the exception is thrown as soon as it is hit. There also may be
* additional futures that errored (but were not hit yet).
*
* If you need to specify a timeout to control how long to block, consider using
* {@link #blockTillAllCompleteOrFirstError(Iterable, long)}.
*
* @param futures Futures to iterate over
* @throws InterruptedException Thrown if thread is interrupted while waiting on future
* @throws ExecutionException Thrown if future throws exception on .get() call
*/
public static void blockTillAllCompleteOrFirstError(Future> ... futures)
throws InterruptedException, ExecutionException {
blockTillAllCompleteOrFirstError(ArrayIterator.makeIterable(futures));
}
/**
* This call blocks till all futures in the list have completed. If the future completed with
* an error an {@link ExecutionException} is thrown. If this exception is thrown, all futures
* may or may not be completed, the exception is thrown as soon as it is hit. There also may be
* additional futures that errored (but were not hit yet).
*
* If you need to specify a timeout to control how long to block, consider using
* {@link #blockTillAllCompleteOrFirstError(Iterable, long)}.
*
* @param futures Structure of futures to iterate over
* @throws InterruptedException Thrown if thread is interrupted while waiting on future
* @throws ExecutionException Thrown if future throws exception on .get() call
*/
public static void blockTillAllCompleteOrFirstError(Iterable extends Future>> futures)
throws InterruptedException, ExecutionException {
if (futures == null) {
return;
}
for (Future> f : futures) {
f.get();
}
}
/**
* This call blocks till all futures in the list have completed. If the future completed with
* an error an {@link ExecutionException} is thrown. If this exception is thrown, all futures
* may or may not be completed, the exception is thrown as soon as it is hit. There also may be
* additional futures that errored (but were not hit yet).
*
* @since 4.0.0
* @param futures Structure of futures to iterate over
* @param timeoutInMillis timeout to wait for futures to complete in milliseconds
* @throws InterruptedException Thrown if thread is interrupted while waiting on future
* @throws TimeoutException Thrown if the timeout elapsed while waiting on futures to complete
* @throws ExecutionException Thrown if future throws exception on .get() call
*/
public static void blockTillAllCompleteOrFirstError(Iterable extends Future>> futures,
long timeoutInMillis)
throws InterruptedException, TimeoutException, ExecutionException {
if (futures == null) {
return;
}
long startTime = Clock.accurateForwardProgressingMillis();
long remainingTime;
for (Future> f : futures) {
if ((remainingTime = timeoutInMillis - (Clock.lastKnownForwardProgressingMillis() - startTime)) <= 0) {
throw new TimeoutException();
}
f.get(remainingTime, TimeUnit.MILLISECONDS);
}
}
/**
* Counts how many futures provided completed with a result that matches the one provided here.
* This can be most useful if your looking to know if an error occurred that was not an
* {@link ExecutionException}. For example assume an API return's {@code Future} and a
* {@code false} represents a failure, this can be used to look for those types of error
* results.
*
* Just like {@link #blockTillAllComplete(Iterable)}, this will block until all futures have
* completed (so we can verify if their result matches or not).
*
* If you need to specify a timeout to control how long to block, consider using
* {@link #countFuturesWithResult(Iterable, Object, long)}.
*
* @since 4.0.0
* @param type of result futures provide to compare against
* @param futures Structure of futures to iterate over
* @param comparisonResult Object to compare future results against to look for match
* @return Number of futures which match the result using a {@link Object#equals(Object)} comparison
* @throws InterruptedException Thrown if thread is interrupted while waiting on future's result
*/
public static int countFuturesWithResult(Iterable extends Future>> futures, T comparisonResult)
throws InterruptedException {
if (futures == null) {
return 0;
}
int resultCount = 0;
for (Future> f : futures) {
if (f.isCancelled()) {
continue;
}
try {
if (comparisonResult == null) {
if (f.get() == null) {
resultCount++;
}
} else if (comparisonResult.equals(f.get())) {
resultCount++;
}
} catch (CancellationException | ExecutionException e) {
// swallowed
}
}
return resultCount;
}
/**
* Counts how many futures provided completed with a result that matches the one provided here.
* This can be most useful if your looking to know if an error occurred that was not an
* {@link ExecutionException}. For example assume an API return's {@code Future} and a
* {@code false} represents a failure, this can be used to look for those types of error
* results.
*
* Just like {@link #blockTillAllComplete(Iterable)}, this will block until all futures have
* completed (so we can verify if their result matches or not).
*
* @since 4.0.0
* @param type of result futures provide to compare against
* @param futures Structure of futures to iterate over
* @param comparisonResult Object to compare future results against to look for match
* @param timeoutInMillis timeout to wait for futures to complete in milliseconds
* @return Number of futures which match the result using a {@link Object#equals(Object)} comparison
* @throws InterruptedException Thrown if thread is interrupted while waiting on future's result
* @throws TimeoutException Thrown if the timeout elapsed while waiting on futures to complete
*/
public static int countFuturesWithResult(Iterable extends Future>> futures,
T comparisonResult, long timeoutInMillis) throws InterruptedException,
TimeoutException {
if (futures == null) {
return 0;
}
int resultCount = 0;
long startTime = Clock.accurateForwardProgressingMillis();
long remainingTime;
for (Future> f : futures) {
if ((remainingTime = timeoutInMillis - (Clock.lastKnownForwardProgressingMillis() - startTime)) <= 0) {
throw new TimeoutException();
}
try {
if (comparisonResult == null) {
if (f.get(remainingTime, TimeUnit.MILLISECONDS) == null) {
resultCount++;
}
} else if (comparisonResult.equals(f.get(remainingTime, TimeUnit.MILLISECONDS))) {
resultCount++;
}
} catch (CancellationException | ExecutionException e) {
// swallowed
}
}
return resultCount;
}
/**
* A potentially more performant option than {@link #makeCompleteFuture(List)} when only a
* listener invocation is desired after all the futures complete. This is effective an async
* implementation of {@link #blockTillAllComplete(Iterable)}. If the listener needs to be
* invoked on another thread than one of the provided futures please use
* {@link #invokeAfterAllComplete(Collection, Runnable, Executor)}. Please see
* {@link ListenableFuture#listener(Runnable)} for more information on execution without an
* {@link Executor}.
*
* It is critical that the collection is NOT modified while this is invoked. A change in the
* futures contained in the collection will lead to unreliable behavior with the exectuion of the
* listener.
*
* @param futures Futures that must complete before listener is invoked
* @param listener Invoked once all the provided futures have completed
*/
public static void invokeAfterAllComplete(Collection extends ListenableFuture>> futures,
Runnable listener) {
invokeAfterAllComplete(futures, listener, null);
}
/**
* A potentially more performant option than {@link #makeCompleteFuture(List)} when only a
* listener invocation is desired after all the futures complete. This is effective an async
* implementation of {@link #blockTillAllComplete(Iterable)}.
*
* It is critical that the collection is NOT modified while this is invoked. A change in the
* futures contained in the collection will lead to unreliable behavior with the exectuion of the
* listener.
*
* @param futures Futures that must complete before listener is invoked
* @param listener Invoked once all the provided futures have completed
* @param executor Executor (or {@code null}) to invoke listener on, see
* {@link ListenableFuture#listener(Runnable, Executor)}
*/
public static void invokeAfterAllComplete(Collection extends ListenableFuture>> futures,
Runnable listener, Executor executor) {
ArgumentVerifier.assertNotNull(listener, "listener");
int size = futures == null ? 0 : futures.size();
if (size == 0) {
if (executor == null) {
listener.run();
} else {
executor.execute(listener);
}
} else if (size == 1) {
futures.iterator().next().listener(listener, executor);
} else {
AtomicInteger remaining = new AtomicInteger(size);
Runnable decrementingListener = () -> {
if (remaining.decrementAndGet() == 0) {
if (executor == null) {
listener.run();
} else {
executor.execute(listener);
}
}
};
for (ListenableFuture> lf : futures) {
lf.listener(decrementingListener);
}
}
}
/**
* Converts a collection of {@link ListenableFuture}'s into a single {@link ListenableFuture}
* where the result will be the first result provided from the collection.
*
* If {@code ignoreErrors} is {@code false} the returned future will complete as soon as the
* first future completes, if it completes in error then the error would be returned. If
* {@code ignoreErrors} is {@code true} then the returned future will complete once a result is
* provided, or once all futures have completed in error. If all futures did complete in error
* then the last error state will be specified to the resulting {@link ListenableFuture}. This
* minor bookkeeping to ignore errors does incur a slight overhead.
*
* @since 6.6
* @param type of result provided in the returned future
* @param c Collection of futures to monitor for result
* @param ignoreErrors {@code false} to communicate the first completed future state, even if in error
* @return A future which will be provided the first result from any in the provided {@link Collection}
*/
public static ListenableFuture makeFirstResultFuture(Collection extends ListenableFuture extends T>> c,
boolean ignoreErrors) {
SettableListenableFuture result = new SettableListenableFuture<>(false);
FutureCallback callback;
int expectedSize = 0;
AtomicInteger atomicSize = null;
if (ignoreErrors) {
expectedSize = c.size();
AtomicInteger errorsRemaining = atomicSize = new AtomicInteger(expectedSize);
callback = new FutureCallback() {
@Override
public void handleResult(T t) {
result.setResult(t);
}
@Override
public void handleFailure(Throwable t) {
if (errorsRemaining.decrementAndGet() == 0) {
// ignore failures till we reach the last failure
result.setFailure(t);
}
}
};
} else {
callback = result;
}
int callbackCount = 0;
for (ListenableFuture extends T> lf : c) {
callbackCount++;
lf.callback(callback);
}
if (callbackCount == 0) {
result.setFailure(new IllegalArgumentException("Empty collection"));
} else if (atomicSize != null && expectedSize != callbackCount) {
atomicSize.addAndGet(callbackCount - expectedSize);
}
return result;
}
/**
* Converts a collection of {@link ListenableFuture}'s into a single {@link ListenableFuture}
* where the result will be the first result provided from the collection.
*
* If {@code ignoreErrors} is {@code false} the returned future will complete as soon as the
* first future completes, if it completes in error then the error would be returned. If
* {@code ignoreErrors} is {@code true} then the returned future will complete once a result is
* provided, or once all futures have completed in error. If all futures did complete in error
* then the last error state will be specified to the resulting {@link ListenableFuture}. This
* minor bookkeeping to ignore errors does incur a slight overhead.
*
* It is expected that the first result is the only result desired, once it is found this will
* attempt to cancel all remaining futures. If you may want other results which were in
* progress, then specifying {@code interruptOnCancel} as {@code false} will mean that any
* futures which started can complete. You can then inspect the collection for done futures
* which might have a result. If there is no concern for other results, then you likely will
* want to interrupt started futures.
*
* @since 5.38
* @param type of result provided in the returned future
* @param c Collection of futures to monitor for result
* @param ignoreErrors {@code false} to communicate the first completed future state, even if in error
* @param interruptOnCancel {@code true} to send a interrupt on any running futures after we have a result
* @return A future which will be provided the first result from any in the provided {@link Collection}
*/
public static ListenableFuture makeFirstResultFuture(Collection extends ListenableFuture extends T>> c,
boolean ignoreErrors, boolean interruptOnCancel) {
SettableListenableFuture result = new SettableListenableFuture<>(false);
FutureCallback callback;
int expectedSize = 0;
AtomicInteger atomicSize = null;
if (ignoreErrors) {
expectedSize = c.size();
AtomicInteger errorsRemaining = atomicSize = new AtomicInteger(expectedSize);
callback = new FutureCallback() {
@Override
public void handleResult(T t) {
if (result.setResult(t)) {
FutureUtils.cancelIncompleteFutures(c, interruptOnCancel);
}
}
@Override
public void handleFailure(Throwable t) {
if (errorsRemaining.decrementAndGet() == 0) {
// ignore failures till we reach the last failure
result.setFailure(t);
}
}
};
} else {
callback = new FutureCallback() {
@Override
public void handleResult(T t) {
if (result.setResult(t)) {
FutureUtils.cancelIncompleteFutures(c, interruptOnCancel);
}
}
@Override
public void handleFailure(Throwable t) {
if (result.setFailure(t)) {
FutureUtils.cancelIncompleteFutures(c, interruptOnCancel);
}
}
};
}
int callbackCount = 0;
for (ListenableFuture extends T> lf : c) {
callbackCount++;
lf.callback(callback);
}
if (callbackCount == 0) {
result.setFailure(new IllegalArgumentException("Empty collection"));
} else if (atomicSize != null && expectedSize != callbackCount) {
atomicSize.addAndGet(callbackCount - expectedSize);
}
return result;
}
/**
* An alternative to {@link #blockTillAllComplete(Iterable)}, this provides the ability to know
* when all futures are complete without blocking. Unlike
* {@link #blockTillAllComplete(Iterable)}, this requires that you provide a collection of
* {@link ListenableFuture}'s. But will return immediately, providing a new
* {@link ListenableFuture} that will be called once all the provided futures have finished.
*
* The future returned will provide a {@code null} result, it is the responsibility of the
* caller to get the actual results from the provided futures. This is designed to just be an
* indicator as to when they have finished. If you need the results from the provided futures,
* consider using {@link #makeCompleteListFuture(Iterable)}. You should also consider using
* {@link #makeFailurePropagatingCompleteFuture(Iterable)}, it has the same semantics as this one
* except it will put the returned future into an error state if any of the provided futures error.
*
* @since 5.3
* @param futures Collection of futures that must finish before returned future is satisfied
* @return ListenableFuture which will be done once all futures provided are done
*/
public static ListenableFuture> makeCompleteFuture(List extends ListenableFuture>> futures) {
if (futures == null || futures.isEmpty()) {
return ImmediateResultListenableFuture.NULL_RESULT;
} else if (futures.size() == 1) {
return futures.get(0);
} else {
return makeCompleteFuture((Iterable extends ListenableFuture>>)futures);
}
}
/**
* An alternative to {@link #blockTillAllComplete(Iterable)}, this provides the ability to know
* when all futures are complete without blocking. Unlike
* {@link #blockTillAllComplete(Iterable)}, this requires that you provide a collection of
* {@link ListenableFuture}'s. But will return immediately, providing a new
* {@link ListenableFuture} that will be called once all the provided futures have finished.
*
* The future returned will provide a {@code null} result, it is the responsibility of the
* caller to get the actual results from the provided futures. This is designed to just be an
* indicator as to when they have finished. If you need the results from the provided futures,
* consider using {@link #makeCompleteListFuture(Iterable)}. You should also consider using
* {@link #makeFailurePropagatingCompleteFuture(Iterable)}, it has the same semantics as this one
* except it will put the returned future into an error state if any of the provided futures error.
*
* @since 5.3
* @param futures Collection of futures that must finish before returned future is satisfied
* @return ListenableFuture which will be done once all futures provided are done
*/
public static ListenableFuture> makeCompleteFuture(Collection extends ListenableFuture>> futures) {
if (futures == null || futures.isEmpty()) {
return ImmediateResultListenableFuture.NULL_RESULT;
} else if (futures.size() == 1) {
return futures.iterator().next();
} else {
return makeCompleteFuture((Iterable extends ListenableFuture>>)futures);
}
}
/**
* An alternative to {@link #blockTillAllComplete(Iterable)}, this provides the ability to know
* when all futures are complete without blocking. Unlike
* {@link #blockTillAllComplete(Iterable)}, this requires that you provide a collection of
* {@link ListenableFuture}'s. But will return immediately, providing a new
* {@link ListenableFuture} that will be called once all the provided futures have finished.
*
* The future returned will provide a {@code null} result, it is the responsibility of the
* caller to get the actual results from the provided futures. This is designed to just be an
* indicator as to when they have finished. If you need the results from the provided futures,
* consider using {@link #makeCompleteListFuture(Iterable)}. You should also consider using
* {@link #makeFailurePropagatingCompleteFuture(Iterable)}, it has the same semantics as this one
* except it will put the returned future into an error state if any of the provided futures error.
*
* @since 1.2.0
* @param futures Futures that must finish before returned future is satisfied
* @return ListenableFuture which will be done once all futures provided are done
*/
public static ListenableFuture> makeCompleteFuture(ListenableFuture> ... futures) {
return makeCompleteFuture(ArrayIterator.makeIterable(futures));
}
/**
* An alternative to {@link #blockTillAllComplete(Iterable)}, this provides the ability to know
* when all futures are complete without blocking. Unlike
* {@link #blockTillAllComplete(Iterable)}, this requires that you provide a collection of
* {@link ListenableFuture}'s. But will return immediately, providing a new
* {@link ListenableFuture} that will be called once all the provided futures have finished.
*
* The future returned will provide a {@code null} result, it is the responsibility of the
* caller to get the actual results from the provided futures. This is designed to just be an
* indicator as to when they have finished. If you need the results from the provided futures,
* consider using {@link #makeCompleteListFuture(Iterable)}. You should also consider using
* {@link #makeFailurePropagatingCompleteFuture(Iterable)}, it has the same semantics as this one
* except it will put the returned future into an error state if any of the provided futures error.
*
* @since 1.2.0
* @param futures Collection of futures that must finish before returned future is satisfied
* @return ListenableFuture which will be done once all futures provided are done
*/
public static ListenableFuture> makeCompleteFuture(Iterable extends ListenableFuture>> futures) {
if (futures == null) {
return ImmediateResultListenableFuture.NULL_RESULT;
}
Iterator extends ListenableFuture>> it = futures.iterator();
if (! it.hasNext()) {
return ImmediateResultListenableFuture.NULL_RESULT;
}
ListenableFuture> result = new EmptyFutureCollection(it);
if (result.isDone()) {
return ImmediateResultListenableFuture.NULL_RESULT;
} else {
return result;
}
}
/**
* An alternative to {@link #blockTillAllComplete(Iterable)}, this provides the ability to know
* when all futures are complete without blocking. Unlike
* {@link #blockTillAllComplete(Iterable)}, this requires that you provide a collection of
* {@link ListenableFuture}'s. But will return immediately, providing a new
* {@link ListenableFuture} that will be called once all the provided futures have finished.
*
* The future returned will provide the result object once all provided futures have completed.
* If any failures occured, they will not be represented in the returned future. If that is
* desired you should consider using
* {@link #makeFailurePropagatingCompleteFuture(Iterable, Object)}, it has the same semantics as
* this one except it will put the returned future into an error state if any of the provided
* futures error.
*
* @since 3.3.0
* @param type of result returned from the future
* @param futures Collection of futures that must finish before returned future is satisfied
* @param result Result to provide returned future once all futures complete
* @return ListenableFuture which will be done once all futures provided are done
*/
@SuppressWarnings("unchecked")
public static ListenableFuture makeCompleteFuture(Iterable extends ListenableFuture>> futures,
final T result) {
if (futures == null) {
return immediateResultFuture(result);
}
Iterator extends ListenableFuture>> it = futures.iterator();
if (! it.hasNext()) {
return immediateResultFuture(result);
}
final EmptyFutureCollection efc = new EmptyFutureCollection(it);
if (efc.isDone()) {
return immediateResultFuture(result);
}
final SettableListenableFuture resultFuture =
new CancelDelegateSettableListenableFuture<>(efc, null);
efc.callback(new FutureCallback