public void shutdown() throws InterruptedException {
        initiateShutdown();
        awaitShutdown();
    }
@Test
    public void testShutdownWhenCalledAfterThreadStart() throws InterruptedException {
        AtomicReference<Optional<Integer>> statusCodeOption = new AtomicReference<>(Optional.empty());
        Exit.setExitProcedure((statusCode, ignored) -> {
            statusCodeOption.set(Optional.of(statusCode));
            // Sleep until interrupted to emulate the fact that `System.exit()` never returns
            Utils.sleep(Long.MAX_VALUE);
            throw new AssertionError();
        });
        CountDownLatch latch = new CountDownLatch(1);
        ShutdownableThread thread = new ShutdownableThread("shutdownable-thread-test") {
            @Override
            public void doWork() {
                latch.countDown();
                throw new FatalExitError();
            }
        };
        thread.start();
        assertTrue(latch.await(10, TimeUnit.SECONDS), "doWork was not invoked");

        thread.shutdown();
        TestUtils.waitForCondition(() -> statusCodeOption.get().isPresent(), "Status code was not set by exit procedure");
        assertEquals(1, statusCodeOption.get().get());
    }