code: public synchronized int stop(long timeout, TimeUnit unit) {
  
      if (isRunning()) {
  
        ExecutorService executorService = Executors.newSingleThreadExecutor(
          newThreadFactory().as(DAEMON_THREAD).in(resolveThreadGroup()).with(THREAD_PRIORITY));
  
        try {
          Future<Integer> futureExitValue = executorService.submit(() -> {
            getProcess().destroy();
            return getProcess().waitFor();
          });
  
          try {
            int exitValue = futureExitValue.get(timeout, unit);
            getLogger().info(String.format("Process [%d] has been stopped", safeGetId()));
            return exitValue;
          }
          catch (ExecutionException e) {
            if (getLogger().isLoggable(Level.FINE)) {
              getLogger().fine(ThrowableUtils.getStackTrace(e));
            }
          }
          catch (InterruptedException e) {
            Thread.currentThread().interrupt();
          }
          catch (TimeoutException e) {
            getLogger().warning(String.format("Process [%1$d] could not be stopped within the given timeout [%2$d ms]",
              safeGetId(), unit.toMillis(timeout)));
          }
        }
        finally {
          executorService.shutdownNow();
        }
  
        return safeExitValue();
      }
      else {
        return exitValue();
      }
    }
docs: Attempts to terminate this {@link Process} within the given timeout if still running.
  {@code #stop(long, TimeUnit)} has no effect if this {@link Process} was previously terminated
  and will just return the exit value.
  
  @param timeout duration to wait for this {@link Process} to stop.
  @param unit {@link TimeUnit} used in the duration to wait for this {@link Process} to stop.
  @return an integer value indicating the exit value of this {@link Process} after it has stopped.
  @see java.util.concurrent.TimeUnit
  @see java.lang.Process#destroy()
  @see java.lang.Process#waitFor()
  @see #isRunning()
  @see #exitValue()
  @see #safeExitValue()