DecorrelatedJitteredBackoffPolicy implements BackoffPolicy { @Override public Duration backoff(Duration previousBackoff) { long prev = previousBackoff.roundTo(TimeUnit.NANOSECONDS); long range = Math.abs(prev * 3 - min); long randBackoff; if (range == 0) { randBackoff = min; } else { randBackoff = min + ThreadLocalRandom.current().nextLong(range); } long backoff = Math.min(max, randBackoff); return new Duration(backoff, TimeUnit.NANOSECONDS); } DecorrelatedJitteredBackoffPolicy(Duration min, Duration max); @Override BackoffPolicy nextAttempt(); @Override Duration backoff(Duration previousBackoff);  }
@Test public void testBackoff() { Duration min = new Duration(1, TimeUnit.MILLISECONDS); Duration max = new Duration(5, TimeUnit.SECONDS); BackoffPolicy policy = new DecorrelatedJitteredBackoffPolicy(min, max); for (int i = 0; i < 1000; i++) { Duration last = new Duration(0, TimeUnit.SECONDS); Duration prev = min; for (int j = 0; j < 1000; j++) { Duration next = policy.backoff(last); assertGreaterThanOrEqual(next, min); assertLessThanOrEqual(next, new Duration(prev.roundTo(TimeUnit.NANOSECONDS) * 3, TimeUnit.NANOSECONDS)); assertLessThanOrEqual(next, max); prev = next; last = next; } } }