Open In App

Random vs ThreadLocalRandom Classes in Java

Improve
Improve
Like Article
Like
Save
Share
Report

The Random Class of the java.util package is used for generating a stream of pseudorandom numbers. It uses a 48-bit seed, which is amended by implementing a Linear Congruential Formula. The general form of a Linear Congruential Formula is an+1 = k * an + c (mod m) where a0 is the seed, a1, a2, … an, an+1 are the random numbers and k, c, m are constants.

If we create two instances of the Random class with the same seed value and call the same sequence of methods for each, they both will return identical sequences of numbers. This property is enforced by specific algorithms defined for this class. The algorithms use a protected utility method which upon invocation can give up to 32 pseudorandomly generated bits. Instances of Random are threadsafe. Although, if the same instances are used across threads they may suffer from contention and result in poor performance. The Instances of Random are not cryptographically safe and therefore should not be used for security-sensitive applications.

Syntax:

public class Random extends Object implements Serializable

Let us take an example, in the program given below we have three instances of the Random class. The first two have the same seed value passed into its constructor. This results in the same number getting generated when we use the nextInt() method of the Random class. But when we change the value of the seed and use it to create the third instance, the number getting generated is different. This example clearly demonstrates the above-stated fact about the instances generating the same sequence of numbers if the same seed value is used and the same methods are used for both. 

Java




// Java Program to illustrate Random class
 
// Importing Random class from java.util utility package
import java.util.Random;
 
// Class
// Main class extending to parent Random class
public class RandomNumbers extends Random {
 
    // Main driver method
    public static void main(String[] args)
    {
 
        // Initialise a seed value
        long seed = 18;
 
        // Create an instance of Random using the seed value
        Random r1 = new Random(seed);
 
        // Printing the primitive datatype-integer
        // by parsing using nextInt() method
        System.out.println(r1.nextInt());
 
        // Create a different instance of Random using the
        // same seed value
        Random r2 = new Random(seed);
 
        // Again, printing the primitive datatype-integer
        // by parsing using nextInt() method
        System.out.println(r2.nextInt());
 
        // Change the seed value to
        // some other random value
        seed = 34;
 
        // Create a new instance using the updated seed
        // value
        Random r3 = new Random(seed);
 
        // Lastly printing the primitive datatype-integer
        // by parsing using nextInt() method
        System.out.println(r3.nextInt());
    }
}


Output

-1148559096
-1148559096
-1167027043

Now dwelling onto the next class that is our ThreadLocalRandom class 

ThreadLocalRandom class present inside the java.util package is also used for generating a stream of pseudo-random numbers. It is a sub-class of the Random class discussed above. As the name suggests this class generates random numbers isolated to the current thread. A ThreadLocalRandom is initialized using an internally generated seed value that is not otherwise modifiable. Using ThreadLocalRandom instead of shared instances of Random will result in low contention and overhead. ThreadLocalRandom, just like its parent class, is not cryptographically secure.

Syntax: 

public class ThreadLocalRandom extends Random 

Implementation: Let us take a scenario where we are creating two simple threads in the main. Inside the run() method we call the ThreadLocalRandom.current.nextInt(). Both the threads use the same value of seed i.e. 10 but give different results because the call to nextInt() is isolated by the thread execution. 

Example 

Java




// Java Program to Illustrate ThreadLocalRandom class
 
// Importing ThreadLocalRandom class from utility package
// named java.util.concurrent package
import java.util.concurrent.ThreadLocalRandom;
 
// Class 1
// Main class extending parent class- Thread
class ThreadLocalRandomNumbers extends Thread {
 
    // Method 1
    // The run() method of the Thread class
    // Must be defined by every class that extends it
    public void run()
    {
 
        // Try block to check for exceptions
        try {
 
            // Initializing a seed value to
            // some random integer value
            int seed = 10;
 
            // Getting the current seed by
            // calling over ThreadLocalRandom class and
            // storing it in a integer variable
            int r
                = ThreadLocalRandom.current().nextInt(seed);
 
            // Printing the generated number r
            // The thread id is obtained using getId()
            System.out.println(
                "Thread " + Thread.currentThread().getId()
                + " generated " + r);
        }
 
        // Catch block to catch the exceptions
        catch (Exception e) {
 
            // Display message on the console if
            // the exception/s occur
            System.out.println("Exception");
        }
    }
 
    // Method 2
    // Main driver method
    public static void main(String[] args)
    {
 
        // Create two threads
        ThreadLocalRandomNumbers t1
            = new ThreadLocalRandomNumbers();
        ThreadLocalRandomNumbers t2
            = new ThreadLocalRandomNumbers();
 
        // Starting th above created threads
        // using the start() method
        t1.start();
        t2.start();
    }
}


Output

Thread 12 generated 7
Thread 11 generated 0

Now we are done with discussing both the classes and have an adequate understanding of both of them. Now wrapping up the article by concluding out the differences between them.

Random ThreadLocalRandom
If different threads use the same instance of Random it results in contention and consequent performance degradation. There is no contention because the random numbers generated are local to the current thread.
Uses Linear Congruential Formula to modify its seed value. The Random generator is initialized using an internally generated seed.
Useful in applications where each thread has its own set of Random instances to use. Useful in applications where multiple threads use random numbers in parallel in thread pools.
This is the Parent class. This is the Child class.

 



Last Updated : 02 Sep, 2022
Like Article
Save Article
Previous
Next
Share your thoughts in the comments
Similar Reads