title: Why does thenComposeAsync await the return to be redeemable
body: <p>I have written up a contrived code example, and it might not be code that someone ought to use, but I believe it <strong>should</strong> work.  However it instead deadlocks.  I've read the answers described <a href="https://stackoverflow.com/questions/26571250/how-to-use-completablefuture-thencomposeasync">here</a>, but found them insufficient.</p>
  <p>Here is the code example:</p>
  <pre><code>import java.util.concurrent.CompletableFuture;
  import java.util.concurrent.Executor;
  import java.util.concurrent.Executors;
  
  public class Test {
  
      public static void main(String argv[]) throws Exception {
          
          int nThreads = 1;
          Executor executor = Executors.newFixedThreadPool( nThreads );
          
  
          
          CompletableFuture.completedFuture(true)
              .thenComposeAsync((unused)-&gt;{
              
                  System.err.println(&quot;About to enqueue task&quot;);
                  CompletableFuture&lt;Boolean&gt; innerFuture = new CompletableFuture&lt;&gt;();
                  executor.execute(() -&gt; {
  
                      // pretend this is some really expensive computation done asynchronously
  
                      System.err.println(&quot;Inner task&quot;);
                      innerFuture.complete(true);
                  });
                  System.err.println(&quot;Task enqueued&quot;);
                               
                  return innerFuture;
              }, executor).get();
  
          System.err.println(&quot;All done&quot;);
          System.exit(0);
  
      }
      
  }
  </code></pre>
  <p>This prints:</p>
  <blockquote>
  <p>About to enqueue task</p>
  <p>Task enqueued</p>
  </blockquote>
  <p>And then it hangs.  It's deadlocked because the executor only has a single thread, and it's waiting for the innerFuture to become redeemable.  Why does &quot;thenComposeAsync&quot; block for its return value to become redeemable, instead of returning the still-incomplete future and freeing up its thread in the executor?</p>
  <p>This feels completely unintuitive, and the javadocs don't really help.  Am I fundamentally misunderstanding how CompletionStages work?  Or is this a bug in the implementation?</p>