Source:
<code><START> public void stop() <END> { stopping = true; taskExecutor.shutdown(); List<ListenableFuture<Void>> shutdownFutures = new ArrayList<>(); synchronized (tasks) { for (ThreadingTaskRunnerWorkItem taskWorkItem : tasks.values()) { shutdownFutures.add(scheduleTaskShutdown(taskWorkItem)); } } controlThreadExecutor.shutdown(); try { ListenableFuture<List<Void>> shutdownFuture = Futures.successfulAsList(shutdownFutures); shutdownFuture.get(); } catch (Exception e) { log.error(e, "Encountered exception when stopping all tasks."); } final DateTime start = DateTimes.nowUtc(); final long gracefulShutdownMillis = taskConfig.getGracefulShutdownTimeout().toStandardDuration().getMillis(); log.info("Waiting up to %,dms for shutdown.", gracefulShutdownMillis); if (gracefulShutdownMillis > 0) { try { final boolean terminated = controlThreadExecutor.awaitTermination( gracefulShutdownMillis, TimeUnit.MILLISECONDS ); final long elapsed = System.currentTimeMillis() - start.getMillis(); if (terminated) { log.info("Finished stopping in %,dms.", elapsed); } else { final Set<String> stillRunning; synchronized (tasks) { stillRunning = ImmutableSet.copyOf(tasks.keySet()); } log.makeAlert("Failed to stop task threads") .addData("stillRunning", stillRunning) .addData("elapsed", elapsed) .emit(); log.warn( "Executor failed to stop after %,dms, not waiting for it! Tasks still running: [%s]", elapsed, Joiner.on("; ").join(stillRunning) ); } } catch (InterruptedException e) { log.warn(e, "Interrupted while waiting for executor to finish."); Thread.currentThread().interrupt(); } } else { log.warn("Ran out of time, not waiting for executor to finish!"); } }</code><technical_language>I wondering if this tied lifecycle stop, WorkerTaskMonitor handle that, wondering ForkingTaskRunner stop is tied lifecycle stop</technical_language>

Target:
public void stop() { stopping = true; taskExecutor.shutdown(); List<ListenableFuture<Void>> shutdownFutures = new ArrayList<>(); synchronized (tasks) { for (ThreadingTaskRunnerWorkItem taskWorkItem : tasks.values()) { shutdownFutures.add(scheduleTaskShutdown(taskWorkItem)); } } controlThreadExecutor.shutdown(); try { ListenableFuture<List<Void>> shutdownFuture = Futures.successfulAsList(shutdownFutures); shutdownFuture.get(); } catch (Exception e) { LOGGER.error(e, "Encountered exception when stopping all tasks."); } final DateTime start = DateTimes.nowUtc(); final long gracefulShutdownMillis = taskConfig.getGracefulShutdownTimeout().toStandardDuration().getMillis(); LOGGER.info("Waiting up to %,dms for shutdown.", gracefulShutdownMillis); if (gracefulShutdownMillis > 0) { try { final boolean terminated = controlThreadExecutor.awaitTermination( gracefulShutdownMillis, TimeUnit.MILLISECONDS ); final long elapsed = System.currentTimeMillis() - start.getMillis(); if (terminated) { LOGGER.info("Finished stopping in %,dms.", elapsed); } else { final Set<String> stillRunning; synchronized (tasks) { stillRunning = ImmutableSet.copyOf(tasks.keySet()); } LOGGER.makeAlert("Failed to stop task threads") .addData("stillRunning", stillRunning) .addData("elapsed", elapsed) .emit(); LOGGER.warn( "Executor failed to stop after %,dms, not waiting for it! Tasks still running: [%s]", elapsed, Joiner.on("; ").join(stillRunning) ); } } catch (InterruptedException e) { LOGGER.warn(e, "Interrupted while waiting for executor to finish."); Thread.currentThread().interrupt(); } } else { LOGGER.warn("Ran out of time, not waiting for executor to finish!"); } }