Search code examples
javaparallel-processingcompletable-future

How Join() works with allOf() method and what is the difference when we use it with single CompletableFuture Object


I need to understand below code. join() method is called from two different place. what is the impact of second join method. can we combine it in one join methods and get the result in list.

CompletableFuture.allOf(futureList.toArray(new CompletableFuture[futureList.size()])).join();
  for(CompletableFuture c: futureList){
     processedDtoIdList.add((Long)c.join());
 }

Thanks in advance.


Solution

  • It looks to me like the second .join call is only there to fetch the actual values from the CompletableFuture objects in the already completed list of futures.

    The join call on CompletableFuture.allOf will wait for all the futures to complete. The join call on each individual future in the for loop will be called on a future that is guaranteed to have completed, and so will just return the value immediately without waiting.

    It seems that this method may be easier to understand if it was rewritten to make this fact explicit, using Future.resultNow instead of CompletableFuture.join:

    CompletableFuture.allOf(
            futureList.toArray(new CompletableFuture[futureList.size()])).join();
    
    for(CompletableFuture c: futureList){
       processedDtoIdList.add((Long)c.resultNow());
    }
    

    Alternatively, the use of CompletableFuture.allOf appears to be redundant here, as the individual futures can be joined on and added to the list as they're completed:

    for(CompletableFuture c: futureList){
       processedDtoIdList.add((Long)c.join());
    }
    

    Javadocs

    CompletableFuture.allOf

    Returns a new CompletableFuture that is completed when all of the given CompletableFutures complete.

    […]

    Among the applications of this method is to await completion of a set of independent CompletableFutures before continuing a program, as in: CompletableFuture.allOf(c1, c2, c3).join();.

    CompletableFuture.join

    Returns the result value when complete, or throws an (unchecked) exception if completed exceptionally.

    Future.resultNow

    Returns the computed result, without waiting.

    This method is for cases where the caller knows that the task has already completed successfully, for example when filtering a stream of Future objects for the successful tasks and using a mapping operation to obtain a stream of results.

    Throws:
    IllegalStateException - if the task has not completed or the task did not complete with a result