private void startNext() {
        if (shuttingDown.get()) {
            // We are shutting down so just exhaust all tasks.
            while (startPending.pollFirst() != null) {
                startRemaining.countDown();
            }

        } else {
            final Provider<Runnable> runnableProvider = startPending.pollFirst();
            if (runnableProvider != null) {
                final Runnable runnable = runnableProvider.get();
                LOGGER.info("Lifecycle " + runnable.getClass().getSimpleName() + " starting up");
                CompletableFuture
                        .runAsync(runnable)
                        .whenComplete((r, t) -> {
                            if (t != null) {
                                while (t instanceof CompletionException) {
                                    t = t.getCause();
                                }
                                LOGGER.error(t.getMessage(), t);
                            }
                            startNext();
                            startRemaining.countDown();
                        });
            }
        }
    }
Called when the application context is destroyed.
stroom-lifecycle/stroom-lifecycle-impl/src/main/java/stroom/lifecycle/impl/LifecycleService.java