Skip to content

Instantly share code, notes, and snippets.

What would you like to do?
package com.stubbornjava.common.concurrent;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CountDownLatch;
import org.jooq.lambda.Unchecked;
import org.jooq.lambda.tuple.Tuple;
import org.jooq.lambda.tuple.Tuple3;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class Futures {
private Futures() {
private static final Logger log = LoggerFactory.getLogger(Futures.class);
private static final CountDownLatch emailLatch = new CountDownLatch(1);
private static final CountDownLatch tagLatch = new CountDownLatch(1);
private static final CountDownLatch roleLatch = new CountDownLatch(1);
public static <T1, T2, T3> Tuple3<T1, T2, T3> joinAll(
CompletableFuture<T1> f1,
CompletableFuture<T2> f2,
CompletableFuture<T3> f3) {
// Do we even need this allOf since we join below anyway.
CompletableFuture.allOf(f1, f2, f3).join();
return Tuple.tuple(f1.join(), f2.join(), f3.join());
private static class User {
private final String email;
private final List<String> tags;
private final List<String> roles;
public User(String email, List<String> tags, List<String> roles) {
super(); = email;
this.tags = tags;
this.roles = roles;
public String getEmail() {
return email;
public List<String> getTags() {
return tags;
public List<String> getRoles() {
return roles;
private static String findEmailById(Long id) {
log.debug("email begin");
Unchecked.supplier(() -> {emailLatch.await(); return null;}).get();
log.debug("email end");
return "";
private static List<String> findTagsByEmail(String email) {
log.debug("tags begin");
Unchecked.supplier(() -> {tagLatch.await(); return null;}).get();
log.debug("tags end");
return Lists.newArrayList("tag1", "tag2");
private static List<String> findRolesByEmail(String email) {
log.debug("roles begin");
Unchecked.supplier(() -> {roleLatch.await(); return null;}).get();
log.debug("roles end");
return Lists.newArrayList("admin", "user");
private static User findUserById(long id) throws InterruptedException {
CompletableFuture<String> emailFuture = CompletableFuture.supplyAsync(() -> findEmailById(1L));
CompletableFuture<List<String>> tagFuture = emailFuture.thenApplyAsync(Futures::findTagsByEmail);
CompletableFuture<List<String>> rolesFuture = emailFuture.thenApplyAsync(Futures::findRolesByEmail);
log.debug("tag latch countdown");
log.debug("email latch countdown");
log.debug("role latch countdown");
return Futures.joinAll(emailFuture, tagFuture, rolesFuture).map(User::new);
public static void main(String[] args) throws InterruptedException {
User user = findUserById(1L);
log.debug("got user " + user.getEmail());
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.