Java 随机数生成:Random vs SecureRandom vs ThreadLocalRandom

全面对比 Java 三种随机数生成器的特点、性能和适用场景。

随机数专题 2026-06-07 8 分钟

Java 随机数生成:Random vs SecureRandom vs ThreadLocalRandom

Java 提供了三种随机数生成器。本文对比它们的特点和适用场景。

Random

基本用法

import java.util.Random;

Random random = new Random();

// 整数
int num = random.nextInt(100); // 0-99

// 浮点数
double d = random.nextDouble(); // 0.0-1.0

// 布尔值
boolean b = random.nextBoolean();

// 高斯分布
double g = random.nextGaussian();

特点

  • 基于线性同余算法
  • 线程安全(但有竞争)
  • 性能一般
  • 不适合安全场景

SecureRandom

基本用法

import java.security.SecureRandom;

SecureRandom secureRandom = new SecureRandom();

// 整数
int num = secureRandom.nextInt(100);

// 字节
byte[] bytes = new byte[16];
secureRandom.nextBytes(bytes);

// 生成密码
String password = secureRandom.ints(12, 33, 123)
    .collect(StringBuilder::new, StringBuilder::appendCodePoint, StringBuilder::append)
    .toString();

特点

  • 加密级随机数
  • 基于操作系统熵源
  • 线程安全
  • 性能较慢

ThreadLocalRandom

基本用法

import java.util.concurrent.ThreadLocalRandom;

// 整数
int num = ThreadLocalRandom.current().nextInt(100);

// 范围
int num = ThreadLocalRandom.current().nextInt(1, 100);

// 浮点数
double d = ThreadLocalRandom.current().nextDouble(0.0, 1.0);

特点

  • 每个线程独立的随机数生成器
  • 无锁竞争
  • 性能最好
  • 不适合安全场景

性能对比

类型 单线程 多线程
Random
SecureRandom
ThreadLocalRandom 最快

测试代码

@Benchmark
public void testRandom() {
    Random random = new Random();
    for (int i = 0; i < 1000000; i++) {
        random.nextInt();
    }
}

@Benchmark
public void testThreadLocalRandom() {
    for (int i = 0; i < 1000000; i++) {
        ThreadLocalRandom.current().nextInt();
    }
}

适用场景

Random

  • 一般用途
  • 单线程场景
  • 不需要安全

SecureRandom

  • 密码生成
  • 令牌生成
  • 密钥生成
  • 安全场景

ThreadLocalRandom

  • 高并发场景
  • 大量随机数生成
  • 不需要安全

常见错误

1. 使用 Random 做安全随机

// ❌ 不安全
String token = new Random().nextInt() + "";

// ✅ 安全
String token = new SecureRandom().nextInt() + "";

2. 多线程使用 Random

// ❌ 有锁竞争
private static final Random random = new Random();

// ✅ 使用 ThreadLocalRandom
int num = ThreadLocalRandom.current().nextInt();

3. 种子可预测

// ❌ 种子可预测
Random random = new Random(12345);

// ✅ 使用默认种子(基于时间)
Random random = new Random();

最佳实践

  1. 安全场景使用 SecureRandom:密码、令牌、密钥
  2. 高并发使用 ThreadLocalRandom:性能最好
  3. 一般场景使用 Random:简单易用
  4. 不要自己实现随机算法:使用标准库

总结

选择随机数生成器时,需要考虑安全性和性能。安全场景用 SecureRandom,高并发用 ThreadLocalRandom,一般场景用 Random。

📚 相关文章