How to Generate Random Number in Java
โก Smart Summary
Random numbers in Java come from four related standard library options, the Random class, Math.random, ThreadLocalRandom, and SecureRandom, each covering a different mix of speed, thread safety, and cryptographic strength for real applications.

Random numbers show up everywhere in Java, from unit-test data and dice-roll games to session tokens and shuffled decks. This tutorial explains how to generate random numbers in Java using every option in the standard library and how to pick the right one for the job.
Generate Random Number in Java
The Java standard library offers four common ways to generate a random number:
java.util.Randomis the general-purpose class. It produces boolean, int, long, float, and double values through methods such asnextInt,nextLong, andnextDouble.Math.randomis a static helper that returns a double between 0.0 (inclusive) and 1.0 (exclusive) using a sharedRandominternally.ThreadLocalRandominjava.util.concurrentgives each thread its own generator, so multiple threads do not contend on a single instance.SecureRandominjava.securityproduces cryptographically strong pseudo-random numbers for passwords, session identifiers, and keys.
The sections below show how to generate ten random numbers with each approach.
Example: Generate Random Number Using Java Random Class
The first example uses java.util.Random to produce ten integers in the range 0 to 99 inclusive:
import java.util.Random; public class RandomNumbers { public static void main(String[] args) { Random objGenerator = new Random(); for (int iCount = 0; iCount < 10; iCount++) { int randomNumber = objGenerator.nextInt(100); System.out.println("Random No : " + randomNumber); } } }
Output:
Random No : 17 Random No : 57 Random No : 73 Random No : 48 Random No : 68 Random No : 86 Random No : 34 Random No : 97 Random No : 73 Random No : 18
An instance of Random is created as objGenerator. The nextInt(int bound) method returns a value between 0 (inclusive) and the supplied bound (exclusive), so nextInt(100) yields values from 0 to 99. To make the sequence reproducible, pass a seed to the constructor, for example new Random(42); the same seed always produces the same sequence, which is useful in tests and simulations.
Example: Using Java Math.random
To generate ten random values in the range 0.0 to 1.0, call the static Math.random method inside a loop. This is the fastest way to obtain a random double without creating a generator object:
public class DemoRandom { public static void main(String[] args) { for (int xCount = 0; xCount < 10; xCount++) { System.out.println(Math.random()); } } }
Output:
0.46518450373334297 0.14859851177803485 0.5628391820492477 0.6323378498048606 0.1740198445692248 0.9140544122258946 0.9167350036262347 0.49251219841030147 0.7426056725722353 0.2039418871298877
Under the hood, Math.random creates a single static Random on first use and calls nextDouble on it. That single shared generator is fine for demos but becomes a bottleneck under heavy multithreaded load, which the next sections address.
Generate a Random Number in a Custom Range
Real programs usually need a random value inside a specific range, such as an integer between 1 and 6 for a dice roll or a double between 10.0 and 20.0 for a simulation. Two patterns cover almost every case.
Random integer between min and max (inclusive):
import java.util.Random; public class RangeDemo { public static void main(String[] args) { Random rnd = new Random(); int min = 1; int max = 6; // nextInt(max - min + 1) returns 0..(max-min), then shift by min int dice = rnd.nextInt(max - min + 1) + min; System.out.println("Dice roll : " + dice); } }
Random double between min and max:
double min = 10.0; double max = 20.0; double value = min + (max - min) * Math.random(); System.out.println("Value : " + value);
Both patterns work by taking a value from the generator’s native range, scaling it to the width of the target range, and shifting it up by the minimum. If you are on Java 8 or later, the same result is available through the newer ints, longs, and doubles stream methods on Random, for example rnd.ints(10, 1, 7).forEach(System.out::println) for ten dice rolls.
ThreadLocalRandom for Multithreaded Code
A single shared Random is thread-safe but slow under contention because every thread has to synchronize on the same internal seed. ThreadLocalRandom, added in Java 7 and living in java.util.concurrent, gives each thread its own generator so there is no lock contention.
import java.util.concurrent.ThreadLocalRandom; public class ThreadLocalDemo { public static void main(String[] args) { // random int in [1, 100] int i = ThreadLocalRandom.current().nextInt(1, 101); // random long in [1000, 5000] long l = ThreadLocalRandom.current().nextLong(1000L, 5001L); // random double in [0.0, 1.0) double d = ThreadLocalRandom.current().nextDouble(); System.out.println(i + " " + l + " " + d); } }
Use ThreadLocalRandom.current() inside worker threads, parallel streams, and any concurrent task. Note that setSeed throws UnsupportedOperationException, so seeding for reproducibility is not supported; if you need a fixed seed, stick with plain Random.
SecureRandom for Security-Sensitive Random Numbers
Instances of Random and ThreadLocalRandom are not cryptographically secure. Given a few output samples, an attacker can reconstruct the internal state and predict future values. For passwords, session tokens, salt values, and cryptographic keys, use java.security.SecureRandom instead. It draws seed material from the operating system entropy pool and produces values that resist prediction.
import java.security.SecureRandom; public class SecureDemo { public static void main(String[] args) { SecureRandom secure = new SecureRandom(); byte[] token = new byte[16]; secure.nextBytes(token); // 128-bit random token int otp = secure.nextInt(1_000_000); // 6-digit one-time code System.out.println("OTP : " + String.format("%06d", otp)); } }
SecureRandom is slower than Random because it uses stronger algorithms and richer seed material. Reserve it for security work and use the faster generators for games, simulations, and test data.
