In this tutorial we will go through those methods of CompletionStage which take another CompletionStage instance as a parameter and combine the both stages' results via BiFunction or BiConsumer or Runnable .
These methods can be categorized as:
thenCombine....(CompletionStage other, BiFunction fn, ....)
thenAcceptBoth....(CompletionStage other, BiConsumer action, ....)
runAfterBoth...(CompletionStage other, Runnable action, ....)
CompletionStage.thenCombine() methods
These methods combine this CompletionStage<T>'s result T with another CompletionStage's result U using a BiFunction. The BiFunction returns a resultant computed value of type V.
public <U,V> CompletableFuture<V> thenCombine(CompletionStage<? extends U> other,
BiFunction<? super T,? super U,? extends V> fn)
public <U,V> CompletableFuture<V> thenCombineAsync(CompletionStage<? extends U> other,
BiFunction<? super T,? super U,? extends V> fn)
public <U,V> CompletableFuture<V> thenCombineAsync(CompletionStage<? extends U> other,
BiFunction<? super T,? super U,? extends V> fn,
Executor executor)
Example
This example uses int[] (from other CompletionStage), finds their values raised to the power of another number (from this CompletionStage) and returns the sum:
package com.logicbig.example;
import java.util.Arrays;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ThreadLocalRandom;
import java.util.stream.IntStream;
public class ThenCombineExample {
public static void main(String[] args) {
CompletableFuture<Integer> cf = CompletableFuture
.supplyAsync(() -> {
int x = ThreadLocalRandom.current().nextInt(1, 5);
System.out.println("Main stage: " + x);
return x;
});
CompletableFuture<Double> finalCf = cf.thenCombine(
getOther(),
(x, ints) -> Arrays.stream(ints).mapToDouble(i -> Math.pow(i, x))
.sum());
Double d = finalCf.join();
System.out.println(d);
}
private static CompletableFuture<int[]> getOther() {
CompletableFuture<int[]> otherCf = CompletableFuture
.supplyAsync(() -> {
int[] ints = IntStream.range(1, 5)
.map(i -> ThreadLocalRandom.current().nextInt(5, 10))
.toArray();
System.out.println("Other stage: " + Arrays.toString(ints));
return ints;
});
return otherCf;
}
}
Main stage: 2 Other stage: [5, 7, 6, 7] 159.0
CompletionStage.thenAcceptBoth() methods
These methods instead of using a BiFunction, use BiConsumer. That means the results from both CompletionStages are consumed and the resultant CompletionStage returns void.
public <U> CompletableFuture<Void> thenAcceptBoth(CompletionStage<? extends U> other,
BiConsumer<? super T, ? super U> action)
public <U> CompletableFuture<Void> thenAcceptBothAsync(CompletionStage<? extends U> other,
BiConsumer<? super T, ? super U> action)
public <U> CompletableFuture<Void> thenAcceptBothAsync(CompletionStage<? extends U> other,
BiConsumer<? super T, ? super U> action,
Executor executor)
Example
package com.logicbig.example;
import java.util.Arrays;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ThreadLocalRandom;
import java.util.stream.IntStream;
public class ThenAcceptBothExample {
public static void main(String[] args) {
CompletableFuture<Integer> cf = CompletableFuture
.supplyAsync(() -> {
int x = ThreadLocalRandom.current().nextInt(1, 5);
System.out.println("Main stage: " + x);
return x;
});
CompletableFuture<Void> finalCf = cf.thenAcceptBoth(
getOther(),
(x, ints) -> {
double sum = Arrays.stream(ints).mapToDouble(n -> Math.pow(n, x))
.sum();
System.out.println(sum);
});
finalCf.join();
}
private static CompletableFuture<int[]> getOther() {
CompletableFuture<int[]> otherCf = CompletableFuture
.supplyAsync(() -> {
int[] ints = IntStream.range(1, 5)
.map(i -> ThreadLocalRandom.current().nextInt(5, 10))
.toArray();
System.out.println("Other stage: " + Arrays.toString(ints));
return ints;
});
return otherCf;
}
}
Main stage: 4 Other stage: [9, 7, 8, 6] 14354.0
CompletionStage.runAfterBoth() methods
These methods simply use a Runnable (instead of a BiFunction or BiConsumer) which is executed after both stages complete normally.
public CompletableFuture<Void> runAfterBoth(CompletionStage<?> other,
Runnable action)
public CompletableFuture<Void> runAfterBothAsync(CompletionStage<?> other,
Runnable action)
public CompletableFuture<Void> runAfterBothAsync(CompletionStage<?> other,
Runnable action,
Executor executor)
Example
package com.logicbig.example;
import java.util.concurrent.CompletableFuture;
public class RunAfterBothExample {
public static void main(String[] args) {
CompletableFuture<Void> cf = CompletableFuture.runAsync(
() -> System.out.println("In first stage"));
CompletableFuture<Void> otherCf = CompletableFuture.runAsync(
() -> System.out.println("In second stage"));
cf.runAfterBoth(otherCf, () -> System.out.println("after both stages"));
cf.join();
}
}
In second stage In first stage after both stages
Example ProjectDependencies and Technologies Used:
|