In previous tutorials we saw, one stage's execution may be triggered by completion of a single stage (composing), or both of two stages (combining). In this tutorial we are going to see that one stage's execution is triggered by completion of either of two stages (whichever completes first).
These methods can be grouped as:
applyToEither....(CompletionStage other, Function fn, .....)
acceptEither....(CompletionStage other, Consumer action, ....)
runAfterEither....(CompletionStage other, Runnable action, ....)
CompletionStage.applyToEither() methods
These methods return a new CompletionStage which is created from 'this' and 'other' given stage. The new CompletionStage is executed when either 'this' or 'other' completion stage completes normally. Whichever stage that finishes first, produces a result, which is fed into the new stage via a function.
public <U> CompletableFuture<U> applyToEither(CompletionStage<? extends T> other,
Function<? super T, U> fn)
public <U> CompletableFuture<U> applyToEitherAsync(CompletionStage<? extends T> other,
Function<? super T, U> fn)
public <U> CompletableFuture<U> applyToEitherAsync(CompletionStage<? extends T> other,
Function<? super T, U> fn, Executor executor)
Example
public class ApplyToEitherExample {
public static void main(String[] args) {
CompletableFuture<Integer> cf =
CompletableFuture.supplyAsync(() -> {
int i = ThreadLocalRandom.current().nextInt(1, 10);
System.out.println("value to be return from 'this' completable: " + i);
return i;
});
CompletableFuture<Double> resultantCf = cf.applyToEither(getOtherCompletable(), a -> {
System.out.println("Selected value: " + a);
return Math.sqrt(a);
});
Double d = resultantCf.join();
System.out.println(d);
}
private static CompletableFuture<Integer> getOtherCompletable() {
return CompletableFuture.supplyAsync(() -> {
int i = ThreadLocalRandom.current().nextInt(1, 10);
System.out.println("value to be return from 'other' completable: " + i);
return i;
});
}
} value to be return from 'other' completable: 6 value to be return from 'this' completable: 7 Selected value: 6 2.449489742783178
In above example both 'this' and 'other' stages executed simultaneously but only one result was used. If any of them is slower to compute then that one is canceled. Let's put delay in one of them to confirm that:
public class ApplyToEitherExample2 {
public static void main(String[] args) {
CompletableFuture<Integer> cf =
CompletableFuture.supplyAsync(() -> {
ThreadSleep(100);
int i = ThreadLocalRandom.current().nextInt(1, 10);
System.out.println("value to be return from 'this' completable: " + i);
return i;
});
CompletableFuture<Double> resultantCf = cf.applyToEither(getOtherCompletable(), a -> {
System.out.println("Selected value: " + a);
return Math.sqrt(a);
});
Double d = resultantCf.join();
System.out.println(d);
}
private static CompletableFuture<Integer> getOtherCompletable() {
return CompletableFuture.supplyAsync(() -> {
int i = ThreadLocalRandom.current().nextInt(1, 10);
System.out.println("value to be return from 'other' completable: " + i);
return i;
});
}
private static void ThreadSleep(int millis) {
try {
Thread.sleep(millis);
} catch (InterruptedException e) {
System.err.println(e);
}
}
} value to be return from 'other' completable: 7 Selected value: 7 2.6457513110645907
CompletionStage.acceptEither() methods
In these methods, instead of a function, a consumer is used to process the result.
public CompletableFuture<Void> acceptEither(
CompletionStage<? extends T> other, Consumer<? super T> action)
public CompletableFuture<Void> acceptEitherAsync(
CompletionStage<? extends T> other, Consumer<? super T> action)
public CompletableFuture<Void> acceptEitherAsync(
CompletionStage<? extends T> other, Consumer<? super T> action,
Executor executor)
Example
public class AcceptEitherExample {
public static void main(String[] args) {
CompletableFuture<Integer> cf =
CompletableFuture.supplyAsync(() -> {
int i = ThreadLocalRandom.current().nextInt(1, 10);
System.out.println("value to be return from 'this' completable: " + i);
return i;
});
CompletableFuture<Void> resultantCf = cf.acceptEither(getOtherCompletable(), a -> {
System.out.println("Selected value: " + a);
System.out.println(Math.sqrt(a));
});
resultantCf.join();
}
private static CompletableFuture<Integer> getOtherCompletable() {
return CompletableFuture.supplyAsync(() -> {
ThreadSleep(100);
int i = ThreadLocalRandom.current().nextInt(1, 10);
System.out.println("value to be return from 'other' completable: " + i);
return i;
});
}
private static void ThreadSleep(int millis) {
try {
Thread.sleep(millis);
} catch (InterruptedException e) {
System.err.println(e);
}
}
} value to be return from 'this' completable: 3 Selected value: 3 1.7320508075688772
CompletionStage.runAfterEither() methods
These methods return a CompletionStage which upon execution, just runs a Runnable .
public CompletableFuture<Void> runAfterEither(CompletionStage<?> other,
Runnable action)
public CompletableFuture<Void> runAfterEitherAsync(CompletionStage<?> other,
Runnable action)
public CompletableFuture<Void> runAfterEitherAsync(CompletionStage<?> other,
Runnable action,
Executor executor)
Example
public class RunAfterEitherExample {
public static void main(String[] args) {
CompletableFuture<Void> cf =
CompletableFuture.runAsync(() -> {
System.out.println("Running 'this' completable");
});
CompletableFuture<Void> resultantCf = cf.runAfterEither(getOtherCompletable(), () -> {
System.out.println("Running after either of the two");
});
resultantCf.join();
}
private static CompletableFuture<Void> getOtherCompletable() {
return CompletableFuture.runAsync(() -> {
ThreadSleep(15);
System.out.println("Running other completable");
});
}
private static void ThreadSleep(int millis) {
try {
Thread.sleep(millis);
} catch (InterruptedException e) {
System.err.println(e);
}
}
} Running 'this' completable Running after either of the two
Example ProjectDependencies and Technologies Used:
|