@Override
    public void run() {
      LOGGER.info("Starting expired delegation token remover thread, "
          + "tokenRemoverScanInterval=" + tokenRemoverScanInterval
          / (60 * 1000) + " min(s)");
      while (running) {
        try {
          long now = System.currentTimeMillis();
          if (lastMasterKeyUpdate + keyUpdateInterval < now) {
            try {
              rollMasterKeyExt();
              lastMasterKeyUpdate = now;
            } catch (IOException e) {
              LOGGER.error("Master key updating failed. "
                  + StringUtils.stringifyException(e));
            }
          }
          if (lastTokenCacheCleanup + tokenRemoverScanInterval < now) {
            renewOrRemoveExpiredTokens();
            lastTokenCacheCleanup = now;
          }
          try {
            Thread.sleep(5000); // 5 seconds
          } catch (InterruptedException ie) {
            LOGGER
            .error("InterruptedException received for ExpiredTokenRemover thread "
                + ie);
          }
        } catch (Throwable t) {
          LOGGER.error("ExpiredTokenRemover thread received unexpected exception. "
                           + t, t);
          // Wait 5 seconds too in case of an exception, so we do not end up in busy waiting for
          // the solution for this exception
          try {
            Thread.sleep(5000); // 5 seconds
          } catch (InterruptedException ie) {
            LOGGER.error("InterruptedException received for ExpiredTokenRemover thread during " +
                "wait in exception sleep " + ie);
          }
        }
      }
    }
Cloned from {@link AbstractDelegationTokenSecretManager} to deal with private access
restriction (there would not be an need to clone the remove thread if the remove logic was
protected/extensible).
standalone-metastore/metastore-server/src/main/java/org/apache/hadoop/hive/metastore/security/TokenStoreDelegationTokenSecretManager.java