private void balanceThrottling(long nextBalanceStartTime, int maxRegionsInTransition,
    long cutoffTime) {
    boolean interrupted = false;

    // Sleep to next balance plan start time
    // But if there are zero regions in transition, it can skip sleep to speed up.
    while (
      !interrupted && EnvironmentEdgeManager.currentTime() < nextBalanceStartTime
        && this.assignmentManager.getRegionStates().hasRegionsInTransition()
    ) {
      try {
        Thread.sleep(100);
      } catch (InterruptedException ie) {
        interrupted = true;
      }
    }

    // Throttling by max number regions in transition
    while (
      !interrupted && maxRegionsInTransition > 0
        && this.assignmentManager.getRegionStates().getRegionsInTransitionCount()
            >= maxRegionsInTransition
        && EnvironmentEdgeManager.currentTime() <= cutoffTime
    ) {
      try {
        // sleep if the number of regions in transition exceeds the limit
        Thread.sleep(100);
      } catch (InterruptedException ie) {
        interrupted = true;
      }
    }

    if (interrupted) Thread.currentThread().interrupt();
  }
It first sleep to the next balance plan start time. Meanwhile, throttling by the max number
regions in transition to protect availability.
@param nextBalanceStartTime   The next balance plan start time
@param maxRegionsInTransition max number of regions in transition
@param cutoffTime             when to exit balancer
hbase-server/src/main/java/org/apache/hadoop/hbase/master/HMaster.java