A Java implementation of the Numerical Recipies random number generator

In many applications, the ThreadLocalRandom class provides a fast, medium-quality random number generator that performs well on statistical tests. It has a period of 264, sufficient for many applications.

Here, we show how we can easily subclass java.util.Random with an implementation of a higher-quality RNG. This example is the "highest quality recommended generator" outlined in Numerical Recipes (see 3rd Ed, p. 342). It is a combined generator: it combines two 64-bit XORShift generators with a 64-bit LCG plus a so-called multiply-with-carry (MWC) generator. It has 192 bits of state and hence a period in the order of 2191 (not strictly 2192, as the MWC component has a period of 263).

A general contract of the java.lang.Random is that it should be thread-safe. We make our subclass thread-safe by using a ReentrantLock and, for simplicity, we lock the entire instance for the duration of the generation routine.

public class HighQualityRandom extends Random {
  private Lock l = new ReentrantLock();
  private long u;
  private long v = 4101842887655102017L;
  private long w = 1;
  
  public HighQualityRandom() {
    this(System.nanoTime());
  }
  public HighQualityRandom(long seed) {
    l.lock();
    u = seed ^ v;
    nextLong();
    v = u;
    nextLong();
    w = v;
    nextLong();
    l.unlock();
  }
  
  public long nextLong() {
    l.lock();
    try {
      u = u * 2862933555777941757L + 7046029254386353087L;
      v ^= v >>> 17;
      v ^= v << 31;
      v ^= v >>> 8;
      w = 4294957665L * (w & 0xffffffff) + (w >>> 32);
      long x = u ^ (u << 21);
      x ^= x >>> 35;
      x ^= x << 4;
      long ret = (x + v) ^ w;
      return ret;
    } finally {
      l.unlock();
    }
  }
  
  protected int next(int bits) {
    return (int) (nextLong() >>> (64-bits));
  }

}