一、核心类概览

类/方法 适用场景 线程安全 特点
Math.random() 简单场景 ✅ 安全 快速但功能有限
java.util.Random 通用场景 ❌ 不安全 功能丰富,可子类化
ThreadLocalRandom 多线程高并发 ✅ 安全 高性能,推荐多线程使用
SecureRandom 安全敏感场景 ✅ 安全 密码学安全,速度慢
SplittableRandom 并行流/函数式 ✅ 安全 Java 8+,适合并行计算

二、方法详解

1. Math.random() —— 最简单方式

// 生成 [0.0, 1.0) 范围内的 double 值
double random = Math.random();

// 生成 [min, max) 范围内的整数
int min = 1, max = 10;
int randomInt = (int)(Math.random() * (max - min)) + min;

// 示例:生成 1-6 的骰子点数
int dice = (int)(Math.random() * 6) + 1;

优点:语法简单,无需导入。
缺点:只能生成 double,范围固定,无法自定义种子。


2. java.util.Random —— 通用随机数生成器

import java.util.Random;

Random random = new Random(); // 使用系统时间作为种子

// 生成各种类型随机数
int randInt = random.nextInt();           // 所有 int 范围
int randInRange = random.nextInt(100);    // [0, 100)
long randLong = random.nextLong();        // 所有 long 范围
boolean randBool = random.nextBoolean();  // true/false
float randFloat = random.nextFloat();     // [0.0, 1.0)
double randDouble = random.nextDouble();  // [0.0, 1.0)

// 生成指定范围的整数 [min, max]
int min = 10, max = 50;
int result = random.nextInt(max - min + 1) + min;

// 使用自定义种子(可重现序列)
Random seeded = new Random(12345L);
System.out.println(seeded.nextInt()); // 每次运行结果相同

优点:类型丰富,支持种子,可预测序列。
注意非线程安全,多线程高并发时性能下降。


3. ThreadLocalRandom —— 高性能并发随机数(推荐多线程)

import java.util.concurrent.ThreadLocalRandom;

// 静态方法调用,无需实例化
ThreadLocalRandom random = ThreadLocalRandom.current();

// 生成随机数
int randInt = random.nextInt();                    // [Integer.MIN_VALUE, Integer.MAX_VALUE)
int randInRange = random.nextInt(1, 101);          // [1, 101) → [1,100]
long randLong = random.nextLong(1000L, 2000L);     // [1000, 2000)
double randDouble = random.nextDouble(0.0, 1.0);   // [0.0, 1.0)

// 示例:生成 1-6 的骰子
int dice = random.nextInt(1, 7);

优点

  • 线程安全且无锁竞争
  • 性能极高,多线程场景首选
  • API 与 Random 兼容

📌 官方推荐:在多线程环境中替代 Random


4. SecureRandom —— 密码学安全随机数

import java.security.SecureRandom;

SecureRandom secureRandom = new SecureRandom();

// 生成安全随机数
byte[] bytes = new byte[16];
secureRandom.nextBytes(bytes); // 填充随机字节

int randInt = secureRandom.nextInt(100); // [0, 100)
String token = secureRandom.ints(8, 48, 123) // 生成8位数字+字母token
    .filter(i -> (i < 58 || i > 64) && (i < 91 || i > 96)) // 过滤特殊字符
    .collect(StringBuilder::new, 
             StringBuilder::appendCodePoint, 
             StringBuilder::append)
    .toString();

优点

  • 密码学安全,不可预测
  • 适合生成密钥、令牌、盐值等

缺点:速度慢,不要用于普通随机需求


5. SplittableRandom —— 并行流友好(Java 8+)

import java.util.SplittableRandom;

SplittableRandom splitRandom = new SplittableRandom();

// 生成随机数
int randInt = splitRandom.nextInt(1, 101);     // [1, 101)
long randLong = splitRandom.nextLong(100, 200); // [100, 200)
double[] doubles = splitRandom.doubles(10).toArray(); // 生成10个随机double

// 与流结合使用
int[] randomArray = splitRandom.ints(100, 1, 1000).toArray(); // 100个1-999的随机数

// 并行流中使用
long count = splitRandom.longs(1_000_000)
    .parallel()
    .filter(x -> x % 2 == 0)
    .count();

优点

  • 专为并行计算设计
  • 支持 split() 生成新实例
  • 性能优秀

📌 适用场景:大数据生成、并行流、函数式编程。


三、生成特定分布的随机数

1. 正态分布(高斯分布)

Random random = new Random();
double gaussian = random.nextGaussian(); // 均值0.0,标准差1.0

// 转换为均值 μ,标准差 σ
double mu = 50.0, sigma = 10.0;
double normal = mu + sigma * gaussian;

2. 随机布尔值(按概率)

Random random = new Random();
double probability = 0.7; // 70% 概率为 true
boolean likelyTrue = random.nextDouble() < probability;

3. 随机选择数组元素

String[] colors = {"红", "绿", "蓝", "黄"};
Random random = new Random();
String randomColor = colors[random.nextInt(colors.length)];

四、最佳实践与注意事项

✅ 推荐用法

场景 推荐类
简单单线程 Math.random()Random
多线程高并发 ThreadLocalRandom首选
安全敏感(密码、token) SecureRandom
并行流/大数据 SplittableRandom

❌ 常见错误

  1. 在多线程中共享 Random 实例

    // 错误!性能差
    private static Random sharedRandom = new Random();
    
    // 正确:使用 ThreadLocalRandom
    ThreadLocalRandom.current().nextInt();
    
  2. Math.random() 生成整数时类型转换错误

    // 错误:可能越界
    int bad = (int) Math.random() * 100;
    
    // 正确
    int good = (int) (Math.random() * 100);
    
  3. SecureRandom 用于普通场景

    // 不推荐:太慢
    // SecureRandom 仅用于安全关键场景
    
  4. 忽略种子的可重现性

    // 调试/测试时可使用固定种子
    Random debugRandom = new Random(42L); // 每次结果相同
    

五、性能对比(简要)

单线程性能 多线程性能 安全性
Math.random() 中等 中等 一般
Random 低 ❌ 一般
ThreadLocalRandom 极高 一般
SecureRandom 低 ❌ 低 ❌
SplittableRandom 一般

六、总结

需求 推荐方案
快速生成一个 0-1 小数 Math.random()
通用随机整数/布尔值 ThreadLocalRandom.current().nextInt()
多线程环境 ThreadLocalRandom
生成密码、令牌 SecureRandom
并行流、大数据生成 SplittableRandom
可重现序列(测试) new Random(seed)

终极建议

  • 日常开发优先使用 ThreadLocalRandom
  • 安全相关必须使用 SecureRandom
  • 避免在高并发中共享 Random 实例

掌握这些随机数生成方式,能让你的 Java 程序更高效、安全、健壮。