If you already had to manage some degree of randomness on Java, chances are you got acquainted with the Math.random() methods.
However, the previous method returns a double.
Beyond very basic use-cases, another option has to be considered, in the form of the java.util.Random class.
Random
An instance of this class is used to generate a stream of pseudorandom numbers.
https://docs.oracle.com/javase/8/docs/api/java/util/Random.html
This root class provides basic random numbers generation capabilities, nothing mind-blowing.
- Generate a single random:
booleanbytearraydoublefloat, whether uniform or from a Gaussian distributionlong- or
int(from 0 to 232 or a specific bound)
- Generate a stream of random:
intlong- or
double
For more specialized needs, there are two children classes, ThreadLocalRandom and SecureRandom.
ThreadLocalRandom
One problem about the Random class is that it’s based on an AtomicLong for number generation.
It’s thread-safe by definition, but it may cause performance issue if used by too many of threads at once.
Use ofThreadLocalRandomis particularly appropriate when multiple tasks (for example, each aForkJoinTask) use random numbers in parallel in thread pools.
https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ThreadLocalRandom.html
Usage is like:
ThreadLocalRandom.current().nextX(...) // (where X is Int, Long, etc.)
There are some interesting things about ThreadLocalRandom:
- Compared to
Random, it adds additional random-generating methods with bounds for typeslonganddouble - It doesn’t use the
next(int bits)for the other random-generating methods, to avoid theAtomicLongcontention
SecureRandom
The important bit about Random is that it doesn’t provide true randomness, but only pseudo-randomness.
From the JavaDoc of the next(int bits)(upon which all other random generator methods depend):
This is a linear congruential pseudorandom number generator, as defined by D. H. Lehmer and described by Donald E. Knuth in The Art of Computer Programming, Volume 3: Seminumerical Algorithms, section 3.2.1.
http://hg.openjdk.java.net/jdk8/jdk8/jdk/file/687fd7c7986d/src/share/classes/java/util/Random.java#l188
On the opposite, SecureRandom offers true randomness:
This class provides a cryptographically strong random number generator (RNG).
A cryptographically strong random number minimally complies with the statistical random number generator tests specified in FIPS 140-2, Security Requirements for Cryptographic Modules, section 4.9.1.
https://docs.oracle.com/javase/8/docs/api/java/security/SecureRandom.html
This class depends on a:
- Provider
-
A
Providerprovides (sic) some or all parts of the Java Security API. It has a name e.g.SunRsaSign, and a version. - Algorithm
-
Pretty self-explanatory, e.g.
NativePRNG
|
Both provider and algorithm are platform-dependent.
It means that randomness obtained by using |
To obtain an instance of the class, one can call either:
- One of the available constructors
- One of the
getInstance()static method - The
getInstanceStrong()static method
I’d suggest using the last option, as it will throw an exception if no "strong" random algorithm is available.
A "strong" algorithm is defined by the securerandom.strongAlgorithms security property.
Running Security.getProperty("securerandom.strongAlgorithms") on my local dev environment yields NativePRNGBlocking:SUN.
I’ll let everyone decide whether an algorithm prefixed with PNRG (Pseudo-Random Number Generator…) is good enough.
Remember to check $JAVA_HOME/lib/security/java.security to manage the security configuration of your JVM.
|