Summary
This proposal introduces new common interface, RandomGenerator
, that would
allow consumers of random numbers to easily migrate between random number
generation services or adapt to new random number generation algorithms as they
are made available. This proposal also introduces a class,
RandomGeneratorFactory
, that can be used to locate and select random number
generation algorithms as they become available. RandomGenerator
and
RandomGeneratorFactory
are implementation outcomes from
JEP 356 Enhanced Pseudo-Random Number Generators.
Problem
Existing random number generators (
java.util.Random
,java.security.SecureRandom
,java.util.concurrent.ThreadLocalRandom
,java.util.SplittableRandom
) require significant effort to adopt if the consumer wishes to change generators (algorithms).The types of services supported by existing random number generators is inconsistent.
Adoption of new random number generation algorithms has a high order of complexity.
Solution
[Note: This proposal avoids the use of pseudo-random with the intent of future
support for stochastic hardware based (noise) random number generation.]
We propose the introduction of a common RandomGenerator
interface to be
implemented by all random generators used in Java. This common interface will
allow easier transition between various implementations of a random number
generator.
RandomGenerator
provides a comprehensive set of methods available from
all random number generators; nextInt
, nextLong
, nextFloat
, nextDouble
,
`nextBoolean
and nextBytes
. As well as bounded versions of the next
methods, RandomGenerator
provides methods for generating streams of
ints, longs and doubles.
To locate and construct application specific number generators, we propose to
introduce the RandomGeneratorFactory<T>
class. RandomGeneratorFactory<T>
uses the ServiceLoader.Provider
mechanism to locate all implementations of
RandomGenerator
.
RandomGeneratorFactory<T>
methods, such as all()
, return
java.util.stream.Stream
of RandomGeneratorFactory
to provide a query
mechanism for locating relevant generators. For example, if the developer wants
a sorted list of all available RandomGenerators then they can print such a list
as follows;
RandomGenerator.all()
.map(RandomGeneratorFactory::name)
.sorted()
.forEach(System.out::println);
The RandomGeneratorFactory<T>
class provides several query and predicate
methods for filtering candidate RandomGenerators. For example, if the developer
needs a generator closest to providing 128 state bits (assuming that a large
number of state bits is more expensive) a query might look like;
RandomGeneratorFactory<RandomGenerator> factory =
RandomGenerator.all()
.filter(f -> 128 <= g.stateBits())
.sorted((f, g) -> Integer.compare(g.stateBits(), f.stateBits()))
.findFirst()
.orElseThrow();
Once a RandomGeneratorFactory<T>
is chosen, a RandomGenerator
can then be
instantiated and utilized;
RandomGenerator rng = factory.create();
System.out.println(rng.nextDouble());
If the name of the RandomGenerator
is known, then the
RandomGenerator.factoryOf
short-cut method can be used;
RandomGeneratorFactory<RandomGenerator> factory = RandomGenerator.factoryOf("Random");
RandomGenerator rng = factory.create();
System.out.println(rng.nextDouble());
As a further shortcut a new instance of RandomGenerator can be constructed
directly using RandomGenerator.of
;
RandomGenerator rng = RandomGenerator.of("Random");
System.out.println(rng.nextDouble());
It is generally suggested that developers not use RandomGenerator.of
by name due
to future depreciation and the potential for better RandomGenerators
. It is
better to use selection queries.
It is proposed that the four existing random number generators will be
implementations of RandomGenerator
; java.util.Random
,
java.security.SecureRandom
, java.util.concurrent.ThreadLocalRandom
and
java.util.SplittableRandom
.
Note that java.util.concurrent.ThreadLocalRandom
will not discoverable via
RandomGeneratorFactory<T>
due to its lack of a no-arg constructor (
ThreadLocalRandom.current()
is used instead), but in all other respects
java.util.concurrent.ThreadLocalRandom
implements RandomGenerator
.
Finally, it is proposed that five specialized sub-interfaces of
RandomGenerator
be introduced; JumpableRandomGenerator
,
LeapableRandomGenerator
, ArbitrariliyJumpableRandomGenerator
,
StreamableRandomGenerator
and SplittableRandomGenerator
. These
sub-interfaces each provide a small set of specialized methods for handling
specific needs. (see enclosed specdiff).
Specification
(see enclosed specdiff)
- csr of
-
JDK-8248862 Implement Enhanced Pseudo-Random Number Generators
-
- Resolved
-
- relates to
-
JDK-8263195 [JEP-356] : SplittableRandom :: makeXXXSpliterator does not state on boundary conditions
-
- Resolved
-
-
JDK-8260329 Update references to TAOCP to latest edition
-
- Resolved
-
-
JDK-8263221 [JEP-356] : SplittableRandom and SplittableGenerators does not specify boundary conditions
-
- Resolved
-
-
JDK-8331687 RandomGeneratorFactory.getDefault() throws exception when the runtime image only has java.base module
-
- Closed
-
- links to