[concurrency-interest] Java 8 CompletableFuture.thenCombine() hangs

Doug Lea dl at cs.oswego.edu
Sun Apr 6 17:40:28 EDT 2014

On 04/01/2014 07:16 PM, Dennis Sosnoski wrote:
> I've run into a situation with CompletableFuture.thenCombine() hanging (i.e.,
> the returned future never completing even though the original future and the
> combined one have completed)
> ...

>          for (int i = 1; i < n; i++) {
>              last = CompletableFuture.supplyAsync(newLambda(i))
> .thenCombine(last, Math::max);
>          }
>          return last.join();
>      }

Which, as Paul Sandoz noted, was due to a StackOverflowError.
Even though this code looks like a loop, it was evaluated recursively
(across multiple threads) which can blow up default-sized runtime
stacks even when n is 10000 or so.

The StackOverflowError was correctly managed by one (or more)
of the intermediate CompletableFutures in the long chain
constructed. But the above code loses reference to intermediate
stages so never noticed. There is probably not very much we can
or should do about this from within CompletableFuture.

However, we can rework propagation in the case of linear
dependency chains, which are the only cases in which these
kinds of StackOverflowErrors occur. By re-packing actions
while processing dependent completions, we can isolate
tail-recursive cases and loopify them. This generally works out
better than moving them across lists, because doing so can
reduce opportunities for other threads to help process them.

I checked in a version that does this at
Also compiled into the jar at
that you can run with -Xbootclasspath

Feel free to try it out. If no problems, I'll start the process
for submitting as a JDK8 update.

Again, the aim here is to avoid StackOverflowError in cases
where users would not expect it. We cannot remove all possible
causes of this or any other resource error.

Thanks to Paul, Martin, Viktor, and Peter for the helpful
suggestions which led to this one.


More information about the Concurrency-interest mailing list