Java Random Numbers Generators

Pseudo-Random Number Generator (PRNG) refers to an algorithm that uses mathematical formulas to produce sequences of random numbers.

In Java, we can use the below four classes to generate random numbers based on our application requirements.

1. RandomGenerator

The RandomGenerator interface parent interface for all the random number generator classes and interfaces. It provides a way to ease the dependency injection mechanism in application code when we want to replace the generator class type from the configuration.

The following classes implement this interface:

  • Random
  • SecureRandom
  • SplittableRandom
  • ThreadLocalRandom

The sub-interfaces are:

  • RandomGenerator.ArbitrarilyJumpableGenerator
  • RandomGenerator.JumpableGenerator
  • RandomGenerator.LeapableGenerator
  • RandomGenerator.SplittableGenerator
  • RandomGenerator.StreamableGenerator

As a rule, objects that implement the RandomGenerator interface need not be thread-safe. It is recommended that multithreaded applications use either ThreadLocalRandom or generators that implement the SplittableGenerator or JumpableGenerator interface.

Objects that implement RandomGenerator are typically not cryptographically secure. Consider using SecureRandom for such uses.

2. java.util.Random Class

The java.util.Random class provides methods that can be used to get a stream of pseudo-random numbers or the next available random number from the given generator’s sequence.

  • If two instances of Random are created with the same seed, and the same sequence of method calls is made for each, they will generate and return identical sequences of numbers.
  • Instances of java.util.Random are threadsafe, but may encounter contention and consequent poor performance in a multi-threaded environment. ThreadLocalRandom in such cases.
  • Instances of java.util.Random are not cryptographically secure. Use  SecureRandom to get a cryptographically secure pseudo-random number generator.

2.1. Stream of Random Numbers

In the given example, we are creating a stream of random integers (IntStream) starting from 10 to 10,000. Then we take 6 numbers from the stream and print them in the console.

IntStream randomNumberStream = new Random().ints(10, 10000);

randomNumberStream
        .limit(6)
        .forEach(System.out::println);
2339
9747
3455
4997
8058
584

Similarly, we can get the DoubleStream and LongStream as well.

2.2. Get Next Random Number from the Generator

If we have an instance of the generator, we can it’s one of the nextXXX() method to get the next available random number.

Random randomGenerator = new Random();

//Upper bound 10000  
System.out.println( randomGenerator.nextInt(10_000) );
System.out.println( randomGenerator.nextInt(10_000) );

//No upper bound
System.out.println( randomGenerator.nextInt() );
System.out.println( randomGenerator.nextInt() );
2481
1166
1912463485
1864493028

Similarly, we have nextBoolean(), nextDouble(), nextFloat(), nextLong() and nextGaussian() methods for providing the desired random output type.

3. java.util.SplittableRandom

SplittableRandom is best suited for isolated parallel computations that may generate subtasks.

Its method split() constructs and returns a new SplittableRandom instance that shares no mutable state with the current instance. However, the values collectively generated by the two generators have the same statistical properties as if these values were generated by a single thread.

Instances of SplittableRandom are not thread-safe. They are designed to be split, not shared, across threads.

SplittableRandom random = new SplittableRandom();
SplittableRandom splitted = random.split();

System.out.println(random.nextInt(10000));
System.out.println(splitted.nextInt(10000));
System.out.println(random.nextInt(10000));
System.out.println(splitted.nextInt(10000));
3865
1707
2820
6988

4. java.security.SecureRandom

SecureRandom class a cryptographically strong subclass of Random. This is used to generate highly random byte sequences generally to be used in security-related algorithms.

  • We can use the constructor of SecureRandom class to provide the name of any specific algorithm we want to use.
  • SecureRandom objects are safe for use by multiple concurrent threads.
SecureRandom random = new SecureRandom("SHA1PRNG");

byte[] bytes = new byte[20];
random.nextBytes(bytes);

Read More: Generate Secure Password Hash

5. java.util.concurrency.ThreadLocalRandom

ThreadLocalRandom is intended to be used in multi-threaded application environment. It is also a specialized version of Random class that is isolated to the current thread.

Instances of ThreadLocalRandom are not cryptographically secure. Consider instead using SecureRandom in security-sensitive applications.

System.out.println( ThreadLocalRandom.current().nextInt(10_000) );
System.out.println( ThreadLocalRandom.current().nextInt(10_000) );

ThreadLocalRandom also provides more methods for generating random doubles, longs or Gaussian random numbers.

Note

To get the most random and reliable results, do not create a new Random object for each new random number.

Create one instance, and use it for generating a random everytime we need it in the application.

6. java.lang.Math.random() Method

Many people will find Math.random() simpler to use. Math.random() returns a positive double number greater than or equal to 0.0 and less than 1.0.

This is static method to it will be created once for the application. When this method is first called, it creates a new pseudorandom-number generator using statement new java.util.Random().

After that, for all calls, this Random instance is used to provide random values pseudorandomly with (approximately) uniform distribution from that range.

This method is properly synchronized to work in a concurrent environment.

for (int counter = 1; counter <= 5; ++counter) 
{
    double randomDouble = Math.random();
    System.out.println( "Generated : " + randomDouble );
}
Generated : 0.19173629711153906
Generated : 0.3182222295780218
Generated : 0.34228976475243933
Generated : 0.45825436773481654
Generated : 0.947437014676154

Happy Learning !!

Was this post helpful?

Join 7000+ Fellow Programmers

Subscribe to get new post notifications, industry updates, best practices, and much more. Directly into your inbox, for free.

2 thoughts on “Java Random Numbers Generators”

  1. Hi Lokesh,

    Your example is good. I would like to add UUID to this solution. This is because the chances of dupes is very minimal (almost never) and can be used in high TPS systems and even in a clustered system.

    public class UUIDTest {

    /**
    * @param args
    */
    public static void main(String[] args) {
    String uuid = UUID.randomUUID().toString();
    System.out.println(uuid);
    }
    }

    Reply

Leave a Comment

HowToDoInJava

A blog about Java and its related technologies, the best practices, algorithms, interview questions, scripting languages, and Python.