Reputation: 9082
I am new to the Java 8 concurrency features such as CompletableFuture
and I hope you can help to get started with the following use case.
There is a service called TimeConsumingServices
that provides time consuming operations which I'd like to run in parallel since all of them are independent.
interface TimeConsumingService {
default String hello(String name) {
System.out.println(System.currentTimeMillis() + " > hello " + name);
return "Hello " + name;
}
default String planet(String name) {
System.out.println(System.currentTimeMillis() + " > planet " + name);
return "Planet: " + name;
}
default String echo(String name) {
System.out.println(System.currentTimeMillis() + " > echo " + name);
return name;
}
default byte[] convert(String hello, String planet, String echo) {
StringBuilder sb = new StringBuilder();
sb.append(hello);
sb.append(planet);
sb.append(echo);
return sb.toString().getBytes();
}
}
So far I implemented the following example and I have managed to call all three service methods in parallel.
public class Runner implements TimeConsumingService {
public static void main(String[] args) {
new Runner().doStuffAsync();
}
public void doStuffAsync() {
CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> this.hello("Friend"));
CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> this.planet("Earth"));
CompletableFuture<String> future3 = CompletableFuture.supplyAsync(() -> this.echo("Where is my echo?"));
CompletableFuture.allOf(future1, future2, future3).join();
}
}
Is there a way to collect the return values of each service call and invoke the method byte[]‘ convert(String, String, String)
?
Upvotes: 15
Views: 23891
Reputation: 2210
You can combine them using thenCombine()
method if there is only 3 futures to complete:
final CompletableFuture<byte[]> byteFuture = future1.thenCombine(future2, (t, u) -> {
StringBuilder sb = new StringBuilder();
sb.append(t);
sb.append(u);
return sb.toString();
}).thenCombine(future3, (t, u) -> {
StringBuilder sb = new StringBuilder();
sb.append(t);
sb.append(u);
return sb.toString();
}).thenApply(s -> s.getBytes());
try {
final byte[] get = byteFuture.get();
} catch (InterruptedException | ExecutionException ex) {
}
Upvotes: 1
Reputation: 2602
To combine the result after you have returned them all you can do something like this
CompletableFuture<byte[]> byteFuture = CompletableFuture.allOf(cf1, cf2, cf3)
.thenApplyAsync(aVoid -> convert(cf1.join(), cf2.join(), cf3.join()));
byte[] bytes = byteFuture.join();
This will run all of your futures, wait for them all to complete, then as soon as they are all finished will call your convert
method you mention.
Upvotes: 19
Reputation: 1452
After join you can simply get()
values from future1
like:
String s1 = future1.get()
and so on
Upvotes: 5