39.1 RandomGenerator and SplittableRandom
Generate high‑quality random values using the modern RandomGenerator API (JDK 17+) and the parallel‑friendly SplittableRandom (JDK 8+).
RandomGenerator Basics (JDK 17+)
import java.util.random.RandomGenerator;
import java.util.random.RandomGeneratorFactory;
// Create a specific algorithm, seeded for reproducibility
RandomGenerator rng = RandomGeneratorFactory
.of("L64X128MixRandom")
.create(42L);
int dice = rng.nextInt(1, 7); // uniform int in [1, 6]
double u = rng.nextDouble(); // uniform in [0.0, 1.0)
double v = rng.nextDouble(10.0); // uniform in [0.0, 10.0)
List available algorithms:
import java.util.random.RandomGeneratorFactory;
RandomGeneratorFactory.all().forEach(f -> System.out.println(f.name()));
Notable algorithms:
- LXM family (e.g.,
L64X128MixRandom,L64X256MixRandom): fast, strong statistical quality; good defaults for simulations. - Xoshiro/Xoroshiro variants: popular, fast; good for many simulation scenarios.
SecureRandom: cryptographically secure for keys/tokens; slower, non‑deterministic across runs.
Stream‑Based Generation
RandomGenerator rng = RandomGeneratorFactory.of("L64X256MixRandom").create();
rng.ints(10, 0, 100).forEach(System.out::println);
rng.doubles(5).forEach(System.out::println);
SplittableRandom (JDK 8+)
SplittableRandom is designed for parallel generation: each split produces an independent child generator.
import java.util.SplittableRandom;
SplittableRandom root = new SplittableRandom(42);
SplittableRandom childA = root.split();
SplittableRandom childB = root.split();
long[] samples = childA.longs(10, 0, 100).toArray();
In parallel tasks, derive a per‑task RNG via split() or a mapped seed (e.g., new SplittableRandom(baseSeed ^ taskId)), avoiding shared generators.
Jumpable/Leapable Generators
Some RandomGenerator implementations support long‑range state advancement:
RandomGenerator g = RandomGeneratorFactory.of("L64X256MixRandom").create(42);
if (g instanceof RandomGenerator.JumpableGenerator jg) {
RandomGenerator gJumped = jg.jump(); // independent stream far ahead in sequence
}
if (g instanceof RandomGenerator.LeapableGenerator lg) {
RandomGenerator gLeaped = lg.leap(); // larger leap distance
}
SecureRandom for Cryptography
import java.security.SecureRandom;
SecureRandom sr = SecureRandom.getInstanceStrong();
byte[] token = new byte[32];
sr.nextBytes(token);
Use SecureRandom for keys/tokens/nonces; avoid non‑crypto generators in security contexts.
Monte Carlo π (Deterministic)
RandomGenerator rng = RandomGeneratorFactory.of("L64X128MixRandom").create(123);
int inside = 0;
int n = 1_000_000;
for (int i = 0; i < n; i++) {
double x = rng.nextDouble();
double y = rng.nextDouble();
if (x*x + y*y <= 1.0) inside++;
}
double piEstimate = 4.0 * inside / (double) n;
Practical Guidance
- Prefer an LXM generator via
RandomGeneratorFactoryfor general simulations. - Use
SplittableRandom(orJumpable/Leapablealgorithms) for parallel workloads. - Seed explicitly and record the algorithm name for reproducibility.
- Use
SecureRandomfor any security‑sensitive needs.