skip to content

Random, SecureRandom & ThreadLocalRandom

java.util.Random is a seedable, predictable PRNG, SecureRandom is the cryptographic one for tokens and keys, and ThreadLocalRandom avoids the contention of sharing a Random between threads. Interviewers ask which you would use to generate a password-reset token.

part ofJavaoverview, primer and where to startread it →
on this pageshow

questions

5

What are java.util.Random, SecureRandom, and ThreadLocalRandom, and when would you choose each?

level: middleimportance: must knowfreq 70%

answer

  1. Random = fast + seedable + predictable
  2. SecureRandom = unpredictable, for tokens/keys/salts
  3. ThreadLocalRandom = per-thread, no contention
  4. security->Secure, concurrency->ThreadLocal, else->Random

basics

~20 s

Random is a basic, fast number generator that can repeat if you give it a seed. SecureRandom makes unpredictable numbers for things like passwords and tokens. ThreadLocalRandom is a faster Random for code where many threads run at once.

solid answer

~40 s

All three produce pseudo-random numbers, but they trade off speed, predictability, and concurrency. java.util.Random is a fast, seedable PRNG (linear congruential) good for simulations, games, and tests where reproducibility helps; it is predictable and must not be used for security. SecureRandom is a cryptographically strong generator backed by the OS/JCA entropy sources; use it for tokens, salts, keys, session IDs, and password resets, where an attacker must not predict output. ThreadLocalRandom gives each thread its own generator, eliminating the contention you get when many threads hammer a single shared Random; reach for it in concurrent code (and never share its instance across threads or seed it for reproducibility). Rule of thumb: security -> SecureRandom; concurrency -> ThreadLocalRandom; everything else -> Random.

go deeper

for a junior

Knows Random makes random numbers and that there's a separate secure one for passwords/tokens.

for a middle

Can name all three, state the security vs concurrency vs general-purpose split, and pick correctly for a given scenario.

for a senior

Explains the mechanisms (LCG predictability, contention on shared Random, entropy sources for SecureRandom) and the access patterns (current() factory, don't seed SecureRandom).

for a principal

Discusses entropy/blocking trade-offs (getInstanceStrong vs new SecureRandom), the Java 17 RandomGenerator unification, and sets team conventions/linting to prevent insecure Random use.

### What 'random' means here Computers cannot produce true randomness from arithmetic. Instead they run a **pseudo-random number generator (PRNG)**: a deterministic function that, starting from an internal number called the **seed**, produces a stream of numbers that *look* random. Same seed in -> same stream out. Java's standard library offers three PRNG-style classes with very different goals. ### 1. java.util.Random The classic, general-purpose PRNG. Internally it is a **linear congruential generator (LCG)** with a 48-bit state, advancing with the formula `state = (state * 0x5DEECE66D + 0xB) mod 2^48`. Key properties: - **Fast and lightweight.** - **Seedable / reproducible:** `new Random(42)` always yields the same sequence. Great for tests, simulations, games, shuffling where you want repeatability. - **Predictable / insecure:** the algorithm and constants are public, and only 48 bits of state. An attacker who sees a couple of outputs can reconstruct the seed and predict all future (and past) values. **Never** use it for anything security-sensitive. - **Thread-safe but contended:** its state is updated with a compare-and-set loop, so when many threads share one `Random`, they fight over the same memory and throughput collapses. ### 2. SecureRandom A **cryptographically strong** PRNG (a CSPRNG). It extends `Random` but overrides the engine with a provider from the **JCA (Java Cryptography Architecture)** that draws from OS entropy (e.g. `/dev/urandom`, Windows CryptGenRandom) and strong algorithms. - **Unpredictable:** designed so that, even seeing many outputs, you cannot predict the next one. This is the whole point. - **Use for:** session IDs, CSRF/password-reset tokens, salts, nonces, key material, anything an attacker would benefit from guessing. - **Cost:** slower than `Random`, and the first call (or `generateSeed`) may briefly block while gathering entropy. Prefer `SecureRandom.getInstanceStrong()` for long-lived keys, or the default constructor `new SecureRandom()` (non-blocking on most platforms) for tokens. - **Don't seed it for reproducibility:** calling `setSeed` to make it deterministic destroys its security guarantee. ### 3. ThreadLocalRandom Introduced in Java 7 to fix the contention problem of a shared `Random` in concurrent code. Each thread gets its **own** generator instance, so there is no shared state and no locking. - **Access via the static factory, never store-and-share:** `ThreadLocalRandom.current().nextInt(bound)`. The instance you get belongs to the calling thread. - **Faster under concurrency** than a shared `Random`, and offers convenient bounded methods like `nextInt(origin, bound)` and `nextDouble(origin, bound)`. - **Not for security** (still a fast statistical PRNG) and **not reproducible** in the usual sense (`setSeed` throws `UnsupportedOperationException`). - **Never share the returned instance across threads** — that reintroduces the exact contention/correctness problem it exists to avoid. ### Decision guide - Need unpredictability for security? -> **SecureRandom**. - Generating randoms from many threads at once? -> **ThreadLocalRandom**. - Single-threaded, want speed and/or reproducibility (tests, sims, games)? -> **Random**. ### Modern note Java 17 added the `RandomGenerator` interface and `RandomGeneratorFactory`, unifying these under one API and adding newer algorithms (e.g. Xoshiro, LXM). The three classes above still implement/relate to it, but the *selection logic by purpose* is unchanged.

  • Why is java.util.Random unsafe for security tokens?
    It is a 48-bit linear congruential generator with public constants; an attacker who observes a few outputs can recover the seed and predict the entire sequence, past and future.
  • What happens if you call setSeed on ThreadLocalRandom?
    It throws UnsupportedOperationException — its design forbids cross-thread reproducible seeding.

saying these in an interview costs you the question

  • Using java.util.Random to generate session tokens or passwords
  • Sharing one ThreadLocalRandom instance across threads
  • Seeding SecureRandom to make it 'reproducible'
  • Claiming Random is unsafe only because it's 'not encrypted' (real reason: tiny predictable state)

context

open as a page

Why is java.util.Random considered predictable and unsuitable for security purposes?

level: seniorimportance: must knowfreq 55%

basics

~20 s

It uses a simple math formula with a small, public starting state. If someone sees a few of its numbers, they can figure out the formula's state and predict every number it will produce next.

open as a page

How do you generate a random number in a range without bias, and how do modern Java APIs help?

level: middleimportance: should knowfreq 35%

basics

~10 s

Use the built-in bounded methods like nextInt(bound) or nextInt(origin, bound) instead of doing 'rng.nextInt() % range'. The modulo trick can make some numbers come up slightly more often.

open as a page

How do you use ThreadLocalRandom correctly, and what problem does it solve compared to a shared Random?

level: middleimportance: should knowfreq 45%

basics

~20 s

Call ThreadLocalRandom.current() each time you need it and use the result right away; never save it and pass it to other threads. It avoids the slowdown you get when many threads share one Random object.

open as a page

How should you use SecureRandom in practice, and what are the common pitfalls (blocking, seeding, getInstanceStrong)?

level: seniorimportance: should knowfreq 40%

basics

~20 s

Create one SecureRandom and reuse it to generate bytes for tokens or keys. Don't give it a fixed seed (that makes it predictable). On some setups it can pause briefly the first time while it gathers randomness.

open as a page