@Override
    public synchronized void shutdown() {
        LOGGER.info("shutdown()");
        executorProvider.setStop(true);

        try {
            // Wait for all tasks to stop executing.
            boolean waiting = true;
            while (waiting) {
                // Stop all of the current tasks.
                taskRegistry.list().forEach(TaskContextImpl::terminate);

                final int currentCount = taskRegistry.list().size();
                waiting = currentCount > 0;
                if (waiting) {
                    // Output some debug to list the tasks that are executing
                    // and queued.
                    LOGGER.info("shutdown() - Waiting for {} tasks to complete. {}",
                            currentCount,
                            taskRegistry.list().stream()
                                    .map(TaskContextImpl::toString)
                                    .collect(Collectors.joining(", ")));

                    // Wait 1 second.
                    Thread.sleep(1000);
                }
            }

            // Shut down all executors.
            executorProvider.shutdownExecutors();
        } catch (final InterruptedException e) {
            LOGGER.error(e.getMessage(), e);

            // Continue to interrupt this thread.
            Thread.currentThread().interrupt();
        }

        executorProvider.setStop(false);
        LOGGER.info("shutdown() - Complete");
    }
Tells tasks to terminate and waits for all tasks to terminate before
cleaning up the executors.
stroom-task/stroom-task-impl/src/main/java/stroom/task/impl/TaskManagerImpl.java