跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客我的书AI学习GitHub 精选镜像AI 生图工具UI配色美学关于
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
Javajava算法

Java 随机数生成器全方位对比

对比了 Java 中多种随机数生成器,包括 java.util.Random、ThreadLocalRandom、SecureRandom、SplittableRandom 及 Java 17+ 的 RandomGenerator。分析了它们的实现原理、线程安全性、性能及适用场景。结论指出:单线程普通场景用 Random,高并发用 ThreadLocalRandom,并行流用 SplittableRandom,安全加密必须用 SecureRandom,科学计算可选 LXM 算法。提供了代码示例与最佳实践建议。

DevStack发布于 2026/3/29更新于 2026/10/20105 浏览

1. 引言

随机数在软件开发中无处不在:模拟、游戏、加密、负载均衡、测试数据生成等。Java 提供了多种随机数生成工具,从最早的 java.util.Random 到专为并发优化的 ThreadLocalRandom,再到高安全性的 SecureRandom 和适用于并行流的 SplittableRandom。此外,第三方库如 Apache Commons Lang 也提供了增强功能。选择合适的随机数生成器对程序性能、安全性和正确性至关重要。

本文将深入剖析每种随机数生成器的特性、实现原理、优缺点及适用场景,并附有详细的性能对比和最佳实践建议。

2. 随机数的基本概念

  • 真随机数:来源于物理现象(如热噪声、量子效应),不可预测,适用于加密、安全令牌。
  • 伪随机数:由算法通过种子生成,看似随机但实际确定,可重现。适用于大多数非安全场景。
  • 种子(Seed):算法的初始状态,相同种子会产生相同随机序列。
  • 周期:伪随机数序列重复之前的长度,长周期更优。

Java 中的随机数生成器都是伪随机的(除了部分 SecureRandom 实现可能使用真随机源),但 SecureRandom 保证了密码学意义上的不可预测性。

3. Java 内置随机数生成器概览

类名引入版本线程安全随机性强度性能主要用途
java.util.Random1.0是(但竞争激烈)中等低并发下较好通用,单线程或低并发
java.util.concurrent.ThreadLocalRandom1.7是,每个线程独立中等并发极高多线程并发随机数
java.security.SecureRandom1.1是高(密码级)较低加密、安全令牌
java.util.SplittableRandom1.8否(但专为 fork/join 设计)中等极快并行流、ForkJoinPool
java.util.random.RandomGenerator 及其实现17各异各异各异统一接口,多种新算法
3.1 java.util.Random

实现原理:使用 48 位种子,线性同余生成器(LCG),公式:seed = (seed * 0x5DEECE66DL + 0xBL) & ((1L << 48) - 1),然后取高位输出。

  • 特点:可指定种子,实例化后即可使用。线程安全(通过原子变量更新种子),但高并发下 CAS 竞争严重,性能下降。
  • 方法:nextInt(), nextLong(), nextDouble(), nextGaussian()(生成高斯分布)等。
  • 示例:
Random rand = new Random(12345L); // 固定种子
int num = rand.nextInt(10); // 0-9
  • 优点:简单易用,可重现。
  • 缺点:并发性能差,随机性不足以用于加密。
3.2 java.util.concurrent.ThreadLocalRandom

实现原理:每个线程持有一个独立的 Random 实例,种子存储在线程本地(Thread 类中的 threadLocalRandomSeed 等字段),避免了共享种子带来的竞争。

  • 特点:单例模式,通过 ThreadLocalRandom.current() 获取当前线程的实例。自动设置种子(初始与线程有关),无需显式实例化。
  • 方法:与 Random 类似,但增加了 nextInt(int bound) 等直接方法。
  • 示例:
int num = ThreadLocalRandom.current().nextInt(1, 100); // 1-99
  • 优点:并发性能极高,适合多线程环境。
  • 缺点:无法设置种子(不可重现),不适用于需要确定性序列的场景。
3.3 java.security.SecureRandom

实现原理:依赖底层操作系统提供的熵源(如 /dev/random、/dev/urandom)或硬件随机数生成器,结合密码学哈希算法(如 SHA1PRNG)生成随机数。

  • 特点:提供强随机性,满足密码学要求(不可预测)。实现可插拔,通过 getInstance(String algorithm) 指定算法。
  • 方法:与 Random 类似,但生成速度慢。
  • 示例:
SecureRandom secureRandom = new SecureRandom(); // 默认算法
byte[] bytes = new byte[16];
secureRandom.nextBytes(bytes); // 生成 16 字节随机数
  • 注意:在 Linux 上,默认使用 /dev/urandom,若需阻塞等待足够熵,可指定 -Djava.security.egd=file:/dev/./urandom。
  • 优点:安全,不可预测。
  • 缺点:性能较低,可能阻塞。
3.4 java.util.SplittableRandom

实现原理:采用改良的 LCG(使用加法和异或),专为拆分成多个独立实例设计。它的 split() 方法返回一个新的 SplittableRandom 实例,该实例与当前实例独立,但共享相同的算法。

  • 特点:非线程安全,但设计用于并行计算,每个线程/任务使用独立的 SplittableRandom 实例。速度极快(比 Random 快 2-3 倍)。
  • 方法:与 Random 类似,但缺少 nextGaussian()。
  • 示例:
SplittableRandom random = new SplittableRandom();
long stream = random.longs(10, 0, 100); // 生成 10 个长整型随机数流
  • 优点:极高性能,适合并行流和 ForkJoin 框架。
  • 缺点:不可用于加密,非线程安全(但可通过 split 保证线程独立)。
3.5 Java 17+ 的 RandomGenerator 接口

Java 17 引入 java.util.random.RandomGenerator 接口,统一了随机数生成器的 API,并提供了多种新算法实现,如 "L32X64MixRandom"、"L64X128StarStarRandom" 等(基于 LXM 系列)。这些算法具有长周期、高状态、高性能的特点。

  • 获取方式:通过 RandomGenerator.of(String name) 或 RandomGenerator.getDefault()。
  • 常见实现:
    • Random、SecureRandom、SplittableRandom 都实现了该接口。
    • 新增算法:L32X64MixRandom、L64X128StarStarRandom、L128X256MixRandom 等,适用于需要高质量随机数的科学计算。
  • 特点:算法多样,可根据需要选择周期和状态大小。
  • 示例:
RandomGenerator rng = RandomGenerator.of("L64X128MixRandom");
long val = rng.nextLong();

4. 第三方库随机数生成器

4.1 Apache Commons Lang - RandomUtils 和 RandomStringUtils

Apache Commons Lang 提供了易用的工具类,内部封装了 java.util.Random 实例。

  • RandomUtils:提供 nextInt、nextLong 等方法,但已废弃,推荐直接使用 JDK 类。
  • RandomStringUtils:生成随机字符串,如字母数字组合。
String randomStr = RandomStringUtils.randomAlphanumeric(10);
  • 注意:内部使用 Random,线程安全但性能一般,且不适用于加密。
4.2 Guava 的随机相关工具

Guava 提供了 com.google.common.hash.Hashing 中的 murmur3_128 等哈希函数,以及 com.google.common.primitives 工具,但没有独立的随机数生成器。对于随机字符串,可以使用 CharMatcher 自行构造。

4.3 其他高性能库
  • FastRandom:某些第三方库(如 commons-math)提供更快的随机数生成器,用于科学计算。
  • OpenJdk 的 jdk.random 包:在 JDK 17 中已内置 LXM 系列,性能极高,无需第三方。

5. 核心对比维度

5.1 线程安全性
  • Random:线程安全,通过 CAS 更新种子,但高并发下性能差。
  • ThreadLocalRandom:线程封闭,无竞争,最佳并发性能。
  • SecureRandom:线程安全,通常使用同步,但性能开销大。
  • SplittableRandom:非线程安全,需通过 split() 为每个线程创建新实例。

结论:并发场景首选 ThreadLocalRandom 或 SplittableRandom(并行流)。

5.2 随机质量与周期
  • Random:周期 2^48,线性同余,低比特位随机性较弱。
  • ThreadLocalRandom:与 Random 算法相同,但种子维护在线程本地。
  • SecureRandom:密码学安全,不可预测。
  • SplittableRandom:周期 2^64,改良算法,分布均匀。
  • JDK 17 LXM 系列:周期可达 2^256 或更高,状态大,质量高。

结论:普通应用 Random 足够,加密用 SecureRandom,高质量科学计算用 LXM。

5.3 性能测试(JMH 简要参考)

以下为粗略性能对比(单位:ns/op,生成 10^7 次 int):

实现单线程多线程(8 线程)
Random20 ns严重下降,约 500 ns(竞争)
ThreadLocalRandom15 ns15 ns(无竞争)
SecureRandom2000 ns2000 ns(阻塞严重)
SplittableRandom8 ns8 ns(每个线程独立实例)
L64X128MixRandom (Java 17)7 ns7 ns(独立实例)

注:实际值随硬件和 JDK 版本变化,但相对关系稳定。

5.4 可重复性(种子控制)
  • Random:支持构造时指定种子,方便重现。
  • ThreadLocalRandom:不支持种子设定。
  • SecureRandom:支持设置种子,但通常用于增加熵而非重现。
  • SplittableRandom:支持种子设定,split() 衍生实例基于当前种子。
  • LXM 算法:支持种子设定。

结论:需要确定性序列(如单元测试)时用 Random 或 SplittableRandom。

5.5 易用性
  • Random 最简单,可直接 new Random()。
  • ThreadLocalRandom 通过静态方法获取,但要注意作用域。
  • SecureRandom 可能抛出异常,需处理 NoSuchAlgorithmException。
  • SplittableRandom 与 Random 类似,但缺少高斯分布方法。

6. 特殊随机数需求

6.1 生成随机字符串

常用场景:验证码、临时密码、ID 生成器。

  • 简单实现:利用 Random 或 ThreadLocalRandom 从字符数组中选取。
  • 安全需求:使用 SecureRandom。
  • 工具类:RandomStringUtils(Commons Lang)或自写:
static String randomString(int length, Random random) {
    String chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
    StringBuilder sb = new StringBuilder(length);
    for (int i = 0; i < length; i++) {
        sb.append(chars.charAt(random.nextInt(chars.length())));
    }
    return sb.toString();
}
6.2 生成随机数流

Java 8+ 的 Random、ThreadLocalRandom、SplittableRandom 都支持直接生成流:

Random rand = new Random();
IntStream ints = rand.ints(10, 0, 100); // 10 个 0-99 的 int

对于并行流,使用 SplittableRandom 的 splits() 方法可以生成多个独立实例,每个处理一段。

6.3 生成指定分布的随机数
  • 高斯分布:Random.nextGaussian() 生成均值为 0,标准差为 1 的正态分布值。
  • 自定义分布:可使用逆变换法或接受 - 拒绝法,或借助第三方库如 Apache Commons Math。
6.4 生成 UUID

Java 内置 UUID.randomUUID() 使用 SecureRandom 生成版本 4 UUID(完全随机)。其性能可能较低,但安全性高。若不需要加密级别,可改用基于 Random 的实现。

7. 深入原理

7.1 线性同余生成器(LCG)

Random 采用 LCG:X_{n+1} = (a * X_n + c) mod m,其中 a=25214903917, c=11, m=2^48。输出时取高比特位(丢弃低 16 位)以改善随机性。LCG 周期短,低比特位周期更短,因此不建议用于蒙特卡洛模拟等需要高质量随机数的场景。

7.2 混合生成器(LXM)

Java 17 引入的 LXM 算法结合了线性同余(LC)和异或移位(XorShift)或混合函数(Mix)。它维护两个状态:一个 LC 状态产生周期性的数值,另一个是加法的 XorShift 状态。最终通过混合函数输出。这种设计具有长周期、高维均匀性,且速度快。

7.3 熵池与阻塞

SecureRandom 在 Linux 上默认读取 /dev/urandom(非阻塞,但初始可能阻塞直到熵池初始化)。若指定 /dev/random,则在熵不足时会阻塞等待。在服务器启动时,若需生成大量安全随机数,建议预先初始化 SecureRandom 或增大熵池(使用 rngd 服务)。

8. 最佳实践与选型建议

8.1 选择指南
  1. 普通应用(非并发):new Random() 或指定种子的 Random。
  2. 多线程并发(无加密需求):ThreadLocalRandom.current()。
  3. 并行流/大数据处理:SplittableRandom 配合 split() 或流 API。
  4. 加密、令牌、密码学:SecureRandom(永远不要用 Random 做安全相关)。
  5. 需要高质量随机数(如模拟)且 JDK 17+:RandomGenerator.of("L64X128MixRandom")。
  6. 单元测试需重现:Random 或 SplittableRandom 固定种子。
8.2 常见陷阱
  • 不要重复实例化 Random:每次 new 会消耗熵(其实影响不大,但若循环内 new 会导致性能差且可能因种子相同产生重复序列)。
  • 不要在并发中共享同一个 Random:应使用 ThreadLocalRandom 或每个线程独立实例。
  • 不要用 Random 生成安全令牌:可被预测。
  • SecureRandom 可能缓慢:预热或异步初始化,避免在性能关键路径上首次调用。
  • Math.random() 内部使用 Random:且每次调用都同步,并发性能差,应避免在多线程中使用。
8.3 代码示例:安全令牌生成
public class TokenGenerator {
    private static final SecureRandom SECURE_RANDOM = new SecureRandom();
    public static String generateToken(int byteLength) {
        byte[] bytes = new byte[byteLength];
        SECURE_RANDOM.nextBytes(bytes);
        return Base64.getUrlEncoder().withoutPadding().encodeToString(bytes);
    }
}
8.4 代码示例:并行流中使用 SplittableRandom
long count = new SplittableRandom()
    .splits(1000) // 生成 1000 个独立实例
    .parallel()
    .mapToLong(rng -> rng.nextLong(1, 100))
    .sum();

9. 未来展望

随着 Java 的发展,随机数生成器将继续演进。目前 RandomGenerator 接口为未来替换算法提供了灵活性。可能的方向包括:

  • 支持硬件随机数指令(如 RDSEED)。
  • 提供更多可插拔算法,适应不同需求。
  • 在虚拟线程环境中,ThreadLocalRandom 仍然适用,因为虚拟线程也是 Thread 的子类,保留了 thread-local 机制。

10. 总结

需求推荐方案备注
单线程普通随机Random简单,可重现
多线程并发随机ThreadLocalRandom最高并发性能
并行流处理SplittableRandom快速且可拆分
安全加密SecureRandom不可预测,性能低
高质量随机(科学计算)JDK 17+ LXM 算法长周期,均匀性好
随机字符串RandomStringUtils 或基于 SecureRandom依场景定

目录

  1. 1. 引言
  2. 2. 随机数的基本概念
  3. 3. Java 内置随机数生成器概览
  4. 3.1 java.util.Random
  5. 3.2 java.util.concurrent.ThreadLocalRandom
  6. 3.3 java.security.SecureRandom
  7. 3.4 java.util.SplittableRandom
  8. 3.5 Java 17+ 的 RandomGenerator 接口
  9. 4. 第三方库随机数生成器
  10. 4.1 Apache Commons Lang - RandomUtils 和 RandomStringUtils
  11. 4.2 Guava 的随机相关工具
  12. 4.3 其他高性能库
  13. 5. 核心对比维度
  14. 5.1 线程安全性
  15. 5.2 随机质量与周期
  16. 5.3 性能测试(JMH 简要参考)
  17. 5.4 可重复性(种子控制)
  18. 5.5 易用性
  19. 6. 特殊随机数需求
  20. 6.1 生成随机字符串
  21. 6.2 生成随机数流
  22. 6.3 生成指定分布的随机数
  23. 6.4 生成 UUID
  24. 7. 深入原理
  25. 7.1 线性同余生成器(LCG)
  26. 7.2 混合生成器(LXM)
  27. 7.3 熵池与阻塞
  28. 8. 最佳实践与选型建议
  29. 8.1 选择指南
  30. 8.2 常见陷阱
  31. 8.3 代码示例:安全令牌生成
  32. 8.4 代码示例:并行流中使用 SplittableRandom
  33. 9. 未来展望
  34. 10. 总结

更多推荐文章

查看全部
  • 低光图像重构与去噪新视角:通用架构与超越
  • Android Framework 核心原理与源码解析指南
  • VS Code 主流 AI 编程插件功能对比与选型
  • AI 大模型时代下易受影响的 20 种职业分析
  • 七种主流大模型微调方法详解:原理与场景对比
  • llama.cpp Docker 镜像国内加速下载地址
  • RAG(检索增强生成)技术详解:原理、架构与实践指南
  • Flutter 三方库 dart_webrtc 在鸿蒙系统上的适配指南
  • QAnything 本地知识库问答系统:支持海量数据与跨语种 RAG 应用
  • Python 爬虫入门实战:100 个项目学习路线与核心技能解析
  • llama.cpp 启动效率优化指南:从加载延迟到毫秒级响应
  • Windows 7 系统运行最新 Python 版本的解决方案
  • 利用闲置小米 9 打造天马 G 复古掌机指南
  • Go Map 底层原理深度解析
  • Verilog 零基础入门:语法、仿真与 FPGA 实战
  • 相干伊辛机在医疗领域及医疗AI领域的应用前景分析
  • MATLAB GUI 实现多算法雷达 CFAR 检测与可视化分析
  • NWPU VHR-10 遥感目标检测数据集详解与 YOLO 训练指南
  • Linux 新手入门:软件安装、Vim 操作与 GCC 编译基础工具链
  • MySQL 内置函数指南:日期、字符串与数学函数实战

相关免费在线工具

  • Keycode 信息

    查找任何按下的键的javascript键代码、代码、位置和修饰符。 在线工具,Keycode 信息在线工具,online

  • Escape 与 Native 编解码

    JavaScript 字符串转义/反转义;Java 风格 \uXXXX(Native2Ascii)编码与解码。 在线工具,Escape 与 Native 编解码在线工具,online

  • JavaScript / HTML 格式化

    使用 Prettier 在浏览器内格式化 JavaScript 或 HTML 片段。 在线工具,JavaScript / HTML 格式化在线工具,online

  • JavaScript 压缩与混淆

    Terser 压缩、变量名混淆,或 javascript-obfuscator 高强度混淆(体积会增大)。 在线工具,JavaScript 压缩与混淆在线工具,online

  • 加密/解密文本

    使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online

  • Gemini 图片去水印

    基于开源反向 Alpha 混合算法去除 Gemini/Nano Banana 图片水印,支持批量处理与下载。 在线工具,Gemini 图片去水印在线工具,online