code: public synchronized void throttle(long numOfBytes) {
      if ( numOfBytes <= 0 ) {
        return;
      }
  
      curReserve -= numOfBytes;
      bytesAlreadyUsed += numOfBytes;
  
      while (curReserve <= 0) {
        long now = System.currentTimeMillis();
        long curPeriodEnd = curPeriodStart + period;
  
        if ( now < curPeriodEnd ) {
          // Wait for next period so that curReserve can be increased.
          try {
            wait( curPeriodEnd - now );
          } catch (InterruptedException ignored) {}
        } else if ( now <  (curPeriodStart + periodExtension)) {
          curPeriodStart = curPeriodEnd;
          curReserve += bytesPerPeriod;
        } else {
          // discard the prev period. Throttler might not have
          // been used for a long time.
          curPeriodStart = now;
          curReserve = bytesPerPeriod - bytesAlreadyUsed;
        }
      }
  
      bytesAlreadyUsed -= numOfBytes;
    }
docs: Given the numOfBytes sent/received since last time throttle was called,
  make the current thread sleep if I/O rate is too fast
  compared to the given bandwidth.
  
  @param numOfBytes
  number of bytes sent/received since last time throttle was called