public class AsyncFunnel<T> extends Object
Used when many clients need the result of an expensive asynchronous operation but only one should
be ongoing at any given time. If doOrGet(java.util.function.Supplier<java.util.concurrent.CompletionStage<T>>)
is called while an operation is
ongoing, the future result of that ongoing task is returned. After the operation completes, a new
task can be created.
For example, imagine we have many threads that will perform a computation on a potentially cached value. If the value is not in the cache, they will have to do an expensive operation to populate the cache. Many threads may discover the value needs to be computed at the same time, but only one thread needs to actually compute it.
AsyncFunnel readFunnel = new AsyncFunnel();
for (int i = 0; i < numThreads; i++) {
CompletableFuture.supplyAsync(() -> {
val = readFromCache();
if (val != null) {
return StageSupport.completedStage(val);
}
// populate the cache if we're first, or just listen for the result on the thread
// already doing the computation if we're not
return readFunnel.doOrGet(() -> {
return expensiveOperation().thenApply(computedVal -> {
updateCache(readVal);
return readVal;
});
});
})
}
Constructor | Description |
---|---|
AsyncFunnel() |
Modifier and Type | Method | Description |
---|---|---|
CompletionStage<T> |
doOrGet(Supplier<CompletionStage<T>> action) |
Runs the provided action, or returns an existing
CompletionStage if an action is
already running. |
public CompletionStage<T> doOrGet(Supplier<CompletionStage<T>> action)
CompletionStage
if an action is
already running. After the returned stage is completed, the first subsequent doOrGet call will
start a new actionaction
- Supplier of a CompletionStage
of T that only runs if no action is
currently runningCompletionStage
produced by action
or one that was previously
producedCopyright © 2018. All rights reserved.