code: public static <E extends Throwable> int backoff(E e, int retryCount, int milliseconds)
          throws E
      {
          if (retryCount <= 0) {
              // Workaround apparent compiler bug.
              org.cojen.util.ThrowUnchecked.fire(e);
          }
          if (milliseconds > 0) {
              Random rnd = cRandom;
              if (rnd == null) {
                  cRandom = rnd = new Random();
              }
              if ((milliseconds = rnd.nextInt(milliseconds)) > 0) {
                  try {
                      Thread.sleep(milliseconds);
                  } catch (InterruptedException e2) {
                  }
                  return retryCount - 1;
              }
          }
          Thread.yield();
          return retryCount - 1;
      }
docs: One strategy for resolving an optimistic lock failure is to try the
  operation again, after waiting some bounded random amount of time. This
  method is provided as a convenience, to support such a random wait.
  <p>
  A retry count is required as well, which is decremented and returned by
  this method. If the retry count is zero (or less) when this method is
  called, then this exception is thrown again, indicating retry failure.
  
  @param retryCount current retry count, if zero, throw this exception again
  @param milliseconds upper bound on the random amount of time to wait
  @return retryCount minus one
  @throws E if retry count is zero