title: Java parallelStream does not use expected number of threads
body: <p>Java 8 parallelStream seems to use more threads than the ones specified by the system property <strong>java.util.concurrent.ForkJoinPool.common.parallelism</strong>. These unit tests show that I process tasks using the desired number of threads using my own ForkJoinPool but when using parallelStream the number of threads is higher than expected.</p>
  
  <pre><code>import org.junit.Test;
  
  import java.util.ArrayList;
  import java.util.List;
  import java.util.concurrent.ForkJoinPool;
  import java.util.concurrent.TimeUnit;
  import java.util.concurrent.atomic.AtomicInteger;
  
  import static org.junit.Assert.assertTrue;
  
  public class ParallelStreamTest {
  
      private static final int TOTAL_TASKS = 1000;
  
      @Test
      public void testParallelStreamWithParallelism1() throws InterruptedException {
          final Integer maxThreads = 1;
          System.setProperty("java.util.concurrent.ForkJoinPool.common.parallelism", maxThreads.toString());
          List&lt;Integer&gt; objects = new ArrayList&lt;&gt;();
          for (int i = 0; i &lt; 1000; i++) {
              objects.add(i);
          }
  
          final AtomicInteger concurrentThreads = new AtomicInteger(0);
          final AtomicInteger taskCount = new AtomicInteger(0);
  
          objects.parallelStream().forEach(i -&gt; {
              processTask(concurrentThreads, maxThreads); //expected to be called one at the time
              taskCount.addAndGet(1);
          });
  
          assertTrue(taskCount.get() == TOTAL_TASKS);
      }
  
      @Test
      public void testMyOwnForkJoinPoolWithParallelism1() throws InterruptedException {
          final Integer threads = 1;
          List&lt;Integer&gt; objects = new ArrayList&lt;&gt;();
          for (int i = 0; i &lt; TOTAL_TASKS; i++) {
              objects.add(i);
          }
  
          ForkJoinPool forkJoinPool = new ForkJoinPool(1);
          final AtomicInteger concurrentThreads = new AtomicInteger(0);
          final AtomicInteger taskCount = new AtomicInteger(0);
  
          forkJoinPool.submit(() -&gt; objects.parallelStream().forEach(i -&gt; {
              processTask(concurrentThreads, threads); //expected to be called one at the time
              taskCount.addAndGet(1);
          }));
          forkJoinPool.shutdown();
          forkJoinPool.awaitTermination(1, TimeUnit.MINUTES);
  
          assertTrue(taskCount.get() == TOTAL_TASKS);
      }
  
      /**
       * It simply processes a task increasing first the concurrentThreads count
       *
       * @param concurrentThreads Counter for threads processing tasks
       * @param maxThreads Maximum number of threads that are expected to be used for processing tasks
       */
      private void processTask(AtomicInteger concurrentThreads, int maxThreads) {
          int currentConcurrentThreads = concurrentThreads.addAndGet(1);
          if (currentConcurrentThreads &gt; maxThreads) {
              throw new IllegalStateException("There should be no more than " + maxThreads + " concurrent thread(s) but found " + currentConcurrentThreads);
          }
  
          // actual processing would go here
  
          concurrentThreads.decrementAndGet();
      }
  }
  </code></pre>
  
  <p>There should be only one thread used for processing tasks as the ForkJoinPool has <code>parallelism=1</code> and <code>java.util.concurrent.ForkJoinPool.common.parallelism=1</code>. Therefore both tests should pass but <strong>testParallelStreamWithParallelism1</strong> fails with:</p>
  
  <blockquote>
    <p>java.lang.IllegalStateException: There should be no more than 1 concurrent thread(s) but found 2</p>
  </blockquote>
  
  <p>It seems that setting <strong>java.util.concurrent.ForkJoinPool.common.parallelism=1</strong> is not working as expected and more than 1 concurrent task is processed simultaneously.</p>
  
  <p>Any ideas?</p>