code: public static <T> List<T> run(Collection<? extends Callable<T>> tasks) throws Exception {
          createThreadPool();
  
          List<T> results = new ArrayList<>();
          if (threads == null) {
              for (Callable<T> task : tasks) {
                  results.add(task.call());
              }
          } else {
              if (threads.getActiveCount() < nprocs) {
                  List<Future<T>> futures = threads.invokeAll(tasks);
                  for (Future<T> future : futures) {
                      results.add(future.get());
                  }
              } else {
                  // Thread pool is busy. Just run in the caller's thread.
                  for (Callable<T> task : tasks) {
                      results.add(task.call());
                  }
              }
          }
          
          return results;
      }
docs: Executes the given tasks serially or parallel depending on the number
  of cores of the system. Returns a list of result objects of each task.
  The results of this method are undefined if the given collection is
  modified while this operation is in progress.
  @param tasks the collection of tasks.
  @return a list of result objects in the same sequential order as
  produced by the iterator for the given task list.
  @throws Exception if unable to compute a result.