public void shutdown() {

    /*
      Here is the thread model of this compactor. There are three groups of threads.
      1. Main thread: This threads submits jobs to worker threads and waits for them to finish.
      2. Worker threads: These threads perform the actual task of compaction.
      3. Shutdown thread: It initiates a graceful shutdown of worker and main threads.
     */

    /*
       Shutdown worker threads, though this may not have an effect if workers are blocked on network calls.
       Drain the task queue and wait for all active worker threads to quit.
     */
    List<Runnable> list = new ArrayList<>();
    logger.info("[COMPACT] Dequeued {} tasks on shutdown and stopping {} active tasks",
        executorService.getQueue().drainTo(list), executorService.getActiveCount());
    cloudDestination.stopCompaction();
    if (!isCompactionDone(cloudConfig.cloudBlobCompactionShutdownTimeoutSecs)) {
      logger.info("[COMPACT] Number of active tasks after stop attempt = {}", executorService.getActiveCount());
    }

    /*
      Shutdown executor.
      This arbitrary wait is merely an attempt to allow the worker threads to gracefully exit.
      We will force a shutdown later. All workers are daemons and JVM _will_ exit when only daemons remain.
      Any data inconsistencies must be resolved separately, but not by trying to predict the right shutdown timeout.
      cloudBlobCompactionShutdownTimeoutSecs is useful for reducing test shutdown times.
    */
    Utils.shutDownExecutorService(executorService, cloudConfig.cloudBlobCompactionShutdownTimeoutSecs,
        TimeUnit.SECONDS);
  }
Shut down the compactor waiting for in progress operations to complete.
ambry-cloud/src/main/java/com/github/ambry/cloud/CloudStorageCompactor.java