title: Design Consideration - Shutdown ForkJoinPool after a certain number of failure
body: <p>I have a list of <code>entities</code>. I'm executing a parallel <code>forEach</code> on this list and performing some operation on every <code>entity</code>. I am running the parallel <code>forEach</code> within a <code>ForkJoinPool</code> so that I can achieve the desired parallelism.</p>
  
  <p>The outline of my existing code is as follows:</p>
  
  <pre><code>ForkJoinPool pool = new ForkJoinPool(4);
  Consumer&lt;Entity&gt; consumer = (Entity entity) -&gt; {
      try {
          doSomething(entity);
      } catch(Exception cause) {
  
      }
  };
  
  try {
      pool.submit(() -&gt; {
          entities.stream()
                  .parallel()
                  .forEach(consumer);
      }).get();
  } finally {
      pool.shutdown();
  }
  </code></pre>
  
  <p>As <code>doSomething()</code> method can throw an exception due to some reason, for example, network connection failure; I would like to stop the parallel processing if the number of consecutive error reaches an error threshold. So the following outline I have thought of:</p>
  
  <pre><code>int errorThreshold = 200;
  AtomicInteger errorCount = new AtomicInteger(0);
  ForkJoinPool pool = new ForkJoinPool(parallelism);
  Consumer&lt;Entity&gt; consumer = (Entity entity) -&gt; {
      boolean success = false;
  
      try {
          doSomething(entity);
          success = true;
      } catch(Exception cause) {        
  
      }
  
      if (!success) {
          if (errorCount.incrementAndGet() == errorThreshold) {
              pool.shutdownNow();
          }
      } else {
          errorCount.set(0);
      }
  };
  
  try {
      pool.submit(() -&gt; {
          entities.stream()
                  .parallel()
                  .forEach(consumer);
      }).get();
  } finally {
      pool.shutdown();
  }
  </code></pre>
  
  <p>Is this the best way to achieve what I want?</p>
  
  <p>P.S.: I'm using jdk8.</p>
  
  <h2>Update</h2>
  
  <p>Sample code:</p>
  
  <pre><code>import java.util.List;
  import java.util.concurrent.CancellationException;
  import java.util.concurrent.ForkJoinPool;
  import java.util.concurrent.atomic.AtomicInteger;
  import java.util.function.Consumer;
  import java.util.stream.Collectors;
  import java.util.stream.IntStream;
  
  public class Main {
  
      private class Entity {
          private int id;
  
          public Entity(int id) {
              this.id = id;
          }
      }
  
      private void execute() throws Exception {
          List&lt;Entity&gt; entities = IntStream.range(0, 1000)
                  .mapToObj(Entity::new)
                  .collect(Collectors.toList());
          int errorThreshold = 5;
          AtomicInteger errorCount = new AtomicInteger(0);
          ForkJoinPool pool = new ForkJoinPool(4);
          Consumer&lt;Entity&gt; consumer = (Entity entity) -&gt; {
              boolean success = false;
  
              try {
                  doSomething(entity);
              } catch (Exception cause) {
                  System.err.println(cause.getMessage());
              }
  
              if (!success) {
                  if (errorCount.incrementAndGet() == errorThreshold) {
                      pool.shutdownNow();
                  }
              } else {
                  errorCount.set(0);
              }
          };
  
          try {
              pool.submit(() -&gt; entities
                      .stream()
                      .parallel()
                      .forEach(consumer))
                      .get();
          } catch (Exception cause) {
              if (CancellationException.class.isInstance(cause)) {
                  System.out.println("ForkJoinPool stopped due to consecutive error");
              } else {
                  throw cause;
              }
          } finally {
              if (!pool.isTerminated()) {
                  pool.shutdown();
              }
          }
      }
  
      private void doSomething(Entity entity) {
          if (isPrime(entity.id)) {
              throw new RuntimeException("Exception occurred for ID: " + entity.id);
          }
  
          System.out.println(entity.id);
      }
  
      private boolean isPrime(int n) {
          if (n == 2) {
              return true;
          }
  
          if (n == 0 || n == 1 || n % 2 == 0) {
              return false;
          }
  
          int limit = (int) Math.ceil(Math.sqrt(n));
  
          for (int i = 3; i &lt;= limit; i += 2) {
              if (n % i == 0) {
                  return false;
              }
          }
  
          return true;
      }
  
      public static void main(String[] args) throws Exception {
          new Main().execute();
      }
  }
  </code></pre>