Search code examples
javaexecutorservicecompletable-futurethreadpoolexecutor

How to use CompletableFuture to use result of first Callable task as arg to all subsequent Callable tasks?


How to use CompletableFuture to use result of first Callable task as arg to all subsequent Callable tasks? I have 3 tasks that need to run like so:

  1. First blocking task runs and returns a value
  2. 2nd and 3rd tasks run asysnchronously with argument supplied from first task and return values.
  3. All 3 values summed up as a final result from all of it.

I tried to do this below, but I am stuck on the .thenApply clause.

I can't quite get this code to work. IN the .thenApply clause, how do I pass an argument from the object response returned?

import com.google.common.util.concurrent.Uninterruptibles;
import java.util.concurrent.*;
public class ThreadPoolTest {

    static ExecutorService threadPool = Executors.newFixedThreadPool(10);
    
    public static void main(String[] args) {
        CompletableFuture<SumCalculator> cf =
          CompletableFuture.supplyAsync(() -> new SumCalculator(100000), threadPool);
        Integer initialResult = cf.getNow(null).call();
        CompletableFuture<SumCalculator> cf2 = CompletableFuture.completedFuture(initialResult)
        .thenApplyAsync((i) -> new SumCalculator(i));
     //  i want to call 2 or more SumCalulator tasks here

        System.out.println("DONE? "  + cf2.isDone());
        System.out.println("message? " + cf2.getNow(null).call());
        threadPool.shutdown();
        System.out.println("Program exit.");
    }

    public static class SumCalculator implements Callable<Integer> {
        private int n;
        public SumCalculator(int n) {
            this.n = n;
        }
        public Integer call() {
            int sum = 0;
            for (int i = 1; i <= n; i++) {
                sum += i;
            }
            Uninterruptibles.sleepUninterruptibly(800, TimeUnit.MILLISECONDS);
            return sum;
        }
    }

}

NOTE: I do want to collect the responses from all 3 tasks together at the end of the Futures as a combined result list, perhaps as a stream of Integer values? In this case, I would want to sum the values. I am wanting to do this for a performance benefit with multiple threads.


Solution

  • If I understood correctly:

        CompletableFuture<Integer> one =
                CompletableFuture.supplyAsync(() -> new SumCalculator(100000).call(), threadPool);
    
        CompletableFuture<Integer> two = one.thenApplyAsync(x -> new SumCalculator(x).call(), threadPool);
        CompletableFuture<Integer> three = one.thenApplyAsync(x -> new SumCalculator(x).call(), threadPool);
    
        Integer result = one.join() + two.join() + three.join();
        System.out.println(result);