title: Default ForkJoinPool executor taking long time
body: <p>I am working with the CompletableFuture for async execution of a stream generated from a list source.</p>
  <p>so i am testing the overloaded method i.e. &quot;supplyAsync&quot; of CompletableFuture in which one method takes only single supplier parameter and other takes a supplier parameter and an executor parameter.
  Here is the documentation for both:</p>
  <p>one</p>
  <blockquote>
  <p>supplyAsync(Supplier supplier)</p>
  <p>Returns a new CompletableFuture that is asynchronously completed by a task running in the ForkJoinPool.commonPool() with the value obtained by calling the given Supplier.</p>
  </blockquote>
  <p>second</p>
  <blockquote>
  <p>supplyAsync(Supplier supplier, Executor executor)</p>
  <p>Returns a new CompletableFuture that is asynchronously completed by a task running in the given executor with the value obtained by calling the given Supplier.</p>
  </blockquote>
  <p>And here is my test class:</p>
  <pre><code>public class TestCompleteableAndParallelStream {
  
      public static void main(String[] args) {
          List&lt;MyTask&gt; tasks = IntStream.range(0, 10)
                  .mapToObj(i -&gt; new MyTask(1))
                  .collect(Collectors.toList());
          
          useCompletableFuture(tasks);
          
          useCompletableFutureWithExecutor(tasks);
  
      }
      
      public static void useCompletableFutureWithExecutor(List&lt;MyTask&gt; tasks) {
            long start = System.nanoTime();
            ExecutorService executor = Executors.newFixedThreadPool(Math.min(tasks.size(), 10));
            List&lt;CompletableFuture&lt;Integer&gt;&gt; futures =
                tasks.stream()
                     .map(t -&gt; CompletableFuture.supplyAsync(() -&gt; t.calculate(), executor))
                     .collect(Collectors.toList());
           
            List&lt;Integer&gt; result =
                futures.stream()
                       .map(CompletableFuture::join)
                       .collect(Collectors.toList());
            long duration = (System.nanoTime() - start) / 1_000_000;
            System.out.printf(&quot;Processed %d tasks in %d millis\n&quot;, tasks.size(), duration);
            System.out.println(result);
            executor.shutdown();
          }
      
      public static void useCompletableFuture(List&lt;MyTask&gt; tasks) {
            long start = System.nanoTime();
            List&lt;CompletableFuture&lt;Integer&gt;&gt; futures =
                tasks.stream()
                     .map(t -&gt; CompletableFuture.supplyAsync(() -&gt; t.calculate()))
                     .collect(Collectors.toList());
           
            List&lt;Integer&gt; result =
                futures.stream()
                       .map(CompletableFuture::join)
                       .collect(Collectors.toList());
            long duration = (System.nanoTime() - start) / 1_000_000;
            System.out.printf(&quot;Processed %d tasks in %d millis\n&quot;, tasks.size(), duration);
            System.out.println(result);
          }
      
      
  
  }
  
  
  class MyTask {
        private final int duration;
        public MyTask(int duration) {
          this.duration = duration;
        }
        public int calculate() {
          System.out.println(Thread.currentThread().getName());
          try {
            Thread.sleep(duration * 1000);
          } catch (final InterruptedException e) {
            throw new RuntimeException(e);
          }
          return duration;
        }
      }
  </code></pre>
  <p>while the &quot;useCompletableFuture&quot; method takes around 4 seconds to complete, &quot;useCompletableFutureWithExecutor&quot; method takes only 1 second to complete.</p>
  <p>No my question is, What different processing does the ForkJoinPool.commonPool() which could do the overhead? In that shouldn't we always prefer the custom executor pool over ForkJoinPool?</p>