code: public Future<ScanResult> scanAsync(final ExecutorService executorService, final int numParallelTasks) {
          try {
              return executorService.submit(new Scanner(scanSpec, executorService, numParallelTasks,
                      /* scanResultProcessor = */ null, /* failureHandler = */ null, topLevelLog));
          } catch (final InterruptedException e) {
              // Interrupted during the Scanner constructor's execution (specifically, by getModuleOrder(),
              // which is unlikely to ever actually be interrupted -- but this exception needs to be caught).
              return executorService.submit(new Callable<ScanResult>() {
                  @Override
                  public ScanResult call() throws Exception {
                      throw e;
                  }
              });
          }
      }
docs: Asynchronously scans the classpath for matching files, returning a {@code Future<ScanResult>}. You should
  assign the wrapped {@link ScanResult} in a try-with-resources statement, or manually close it when you are
  finished with it.
  
  @param executorService
  A custom {@link ExecutorService} to use for scheduling worker tasks.
  @param numParallelTasks
  The number of parallel tasks to break the work into during the most CPU-intensive stage of
  classpath scanning. Ideally the ExecutorService will have at least this many threads available.
  @return a {@code Future<ScanResult>}, that when resolved using get() yields a new {@link ScanResult} object
  representing the result of the scan.