RetryUtil { public Duration calculateDelay(int consecutiveFailures) { final int cappedTries = Math.min(consecutiveFailures, maxExponent); final int multiplier = Math.max(1, RANDOM.nextInt(1 << cappedTries)); return baseDelay.multipliedBy(multiplier); } RetryUtil(Duration baseDelay, int maxExponent); Duration calculateDelay(int consecutiveFailures);  }
@Test public void shouldCalculateExpectedAverage() throws Exception { List<Long> delays = new ArrayList<>(); int runs = 10000; for (int i = 0; i < runs; i++) { delays.add(retryUtil.calculateDelay(MAX_EXPONENT).toMillis()); } double average = delays.stream() .mapToLong(i -> i) .average() .orElseThrow(); double expected = BASE_DELAY.toMillis() * (1 << (MAX_EXPONENT - 1)); double diff = Math.abs(expected - average); assertThat(diff, lessThan(expected * 0.05)); }