There are many applications where we need to generate numbers that appear to be "random" or unpredictable. At its simplest, we can generate a random number in Java with a line of code such as the following:

int diceRoll = 1 + ThreadLocalRandom.current().nextInt(6);

This is the simplest way to generate a random number in Java and the appropriate method to use in many cases. However, depending on your application, a more in-depth understanding of random number generators may be required. For example:

- we may need to generate other data types, such as random longs, doubles etc;
- we may need to know
*how many*numbers the algorithm is suitable for generating; - we may need
*strong guarantees*about the level of unpredictability or statistical properties of the random numbers generated (how "like a real dice" are the numbers generated by the method above? can one user guess another user's secret number?); - in
*simulations*of non-linear quantities such as network response times, we may need to generate random numbers with different types of distribution; - we may have
*performance*or*thread-safety*concerns.

Read on for more details of these issues and the various options available for generating random numbers in Java.

For the reasons outlined above, there are actually various different random number generators in the Java platform.
The following random nubmer generators are currently provided in the Java platform "out of the box", with the `Random`
base class offering the possibility of custom subclasses:

Class | Quality | Speed | Period | When to use |
---|---|---|---|---|

java.util.Random |
Low | Medium | 2^{48} |
Legacy uses or for subclassing. The LCG algorithm used by It is still the base class if you
want to plug in your own basic RNG implementation and take advantage of methods that sit on top of it
such as |

ThreadLocalRandom |
Medium | Fast | 2^{64} |
This is the general-purpose class to use in most cases, unless you need to guarantee that
you are using a specific algorithm, will be working with a very large number of threads or
need to be able to set predictable seeds. For more information,
see the explanation of ThreadLocalRandom. |

SecureRandom |
Very High | Slow | 2^{160} |
Used where you need very high quality or cryptographic strength
random numbers. For more information, see explanation of SecureRandom. |

SplittableRandom |
Medium | Fast | 2^{64} per instance |
Used when a very large number of random numbers need to be generated and/or when
large number of separate geneartor instances are needed to perform a joint
task, e.g. for a very large number of threads working together or in certain
divide-and-conquer algorithms. For more information, see explanation of SplittableRandom. |

At the time of writing, there is a proposal underway (see JEP 356: Enhanced Pseudo-Random Number Generators) to add further RNG algorithms to the Java platform.

The simple line of code above glosses over a lot of complexity.
We want to produce "unpredictable" numbers yet the whole point of computer instructions is that,
for a given input, they are designed to produce a predictable
result. So random number generation algorithms must generally take whatever tiny amount of "physical" randomness
might be available, e.g. the current clock time in milliseconds or nanoseconds^{1}, and then use this as a
*seed* to generate a sequence that to the observer, *appears* to be unpredictable.
As well as being unpredictable, we generally want computer-genreated random numbers to have similar statistical
properties to the "real" sources of unpredictability they are simulating. For example, if we write a
routine to simulate rolling a six-sided dice, we would like each of the numbers 1-6 to
come up with equal probability. And if the routine is used to generate two rolls in succession, we would
like it to appear as though the two rolls were completely independent, just as if we were rolling two
physical dice.

In some cases, we need random numbers to be so unpredictable that money or the security of a system depend on it
(i.e. they are *cryptographically secure*).
For example, if we assign a random encryption key to one user of a web site or remote system, we don't want that user to be able to
determine the next user's encryption key based on the one assigned to them.

A large number of random number generation techniques have been devised over the years to address the above needs. Each one is generally a tradeoff: how much CPU time and memory usage are we willing to dedicate to achieving the goals of statistical fairness and unpredictability given our intended use? Java includes various random number generators in the standard JDK, and makes it relatively staightforward to plug in additional algorithms if required.

The following pages contain further information on the ranodm number generators listed above, as well as further alternatives:

1. These sources of "physical" randomness or "real unpredictability" are generally referred to as *entropy*.
Clock time is the most common source, but other sources could include e.g. CPU temperature
sensors, noise from analogue sound card inputs, timings from physical disk activity (in the age of spinny disks at least!),
recent mouse movement etc. With each of these sources, there are whole discussions to be had on how
good a source of entropy they are.

1. What we're describing here is sometimes more specifically called
a *uniform* random number generator. We could equally have a generator where
numbers occur randomly with some non-linear *distribution*.
For example, in a later section, we discuss generating
numbers with a normal distribution, which is needed in certain simulation
applications.