上一篇
Java如何简单生成随机数?
- 后端开发
- 2025-06-12
- 4370
Java使用RandomAccessFile类实现文件随机写入,通过seek()方法定位文件指针到指定位置,再调用write()方法写入数据,写入会覆盖当前位置的原有内容,支持字节、数组等多种数据类型写入。
Math.random():基础随机数生成
原理
静态方法 Math.random()
返回 [0.0, 1.0)
之间的 double
值,底层基于 java.util.Random
实现。
适用场景
简单场景(如快速原型、非关键性随机值)。
代码示例
// 生成 [0, 100) 的整数 int num = (int) (Math.random() * 100); // 生成 [10, 20) 的浮点数 double decimal = 10 + Math.random() * 10;
注意
- 线程安全但性能一般
- 无法设置随机种子(可复现性差)
java.util.Random:灵活可控的随机数
原理
通过伪随机数算法(线性同余)生成整数、浮点数或布尔值。
适用场景
单线程环境下的通用随机需求(如模拟数据)。
代码示例
Random random = new Random(); // 生成 [0, 100) 的整数 int num = random.nextInt(100); // 生成 [-50, 50) 的整数 int rangeNum = random.nextInt(100) - 50; // 设置种子(可复现结果) Random seededRandom = new Random(12345);
优点
- 支持种子(可复现测试)
- 提供多种数据类型(nextBoolean(), nextDouble())
缺点 - 多线程下性能瓶颈(需同步锁)
ThreadLocalRandom:高并发优化
原理
为每个线程分配独立随机数生成器,避免资源竞争。
适用场景
多线程高并发场景(如服务器端批量任务)。
代码示例
// 生成 [1, 100] 的整数 int num = ThreadLocalRandom.current().nextInt(1, 101); // 生成高斯分布随机值 double gaussian = ThreadLocalRandom.current().nextGaussian();
优点
- 线程间无竞争(性能提升显著)
- 无需显式初始化
注意 - Java 7+ 支持
- 不可设置全局种子(每个线程独立种子)
SecureRandom:密码学安全随机数
原理
基于操作系统熵源(如硬件噪声)生成不可预测的随机数,符合 FIPS 140-2 安全标准。
适用场景
安全敏感操作(如令牌生成、加密密钥)。
代码示例
SecureRandom secureRandom = new SecureRandom(); // 生成20字节的安全随机数 byte[] bytes = new byte[20]; secureRandom.nextBytes(bytes); // 生成大范围整数(0 到 2^48-1) long secureLong = secureRandom.nextLong() & 0xFFFFFFFFFFFFL;
优点
- 抗预测攻击(适用于密码学)
- 支持多种算法(如 NativePRNG、SHA1PRNG)
缺点 - 性能较低(比
Random
慢 10-50 倍) - 初始化可能阻塞(等待系统熵)
方法对比与选型建议
方法 | 线程安全 | 性能 | 安全性 | 适用场景 |
---|---|---|---|---|
Math.random() |
简单快速生成 | |||
Random |
(需同步) | 单线程可控随机 | ||
ThreadLocalRandom |
高并发、多线程任务 | |||
SecureRandom |
加密、令牌、密钥生成 |
最佳实践
- 优先用
ThreadLocalRandom
替代Random
(Java 7+项目)- 敏感数据必须用
SecureRandom
- 测试时通过固定种子(
Random(seed)
)复现结果
引用说明
- Oracle官方文档:Random类
- Java安全指南:SecureRandom
- 并发编程实践:ThreadLocalRandom
- 密码学标准:NIST FIPS 140-2(安全随机数规范)
通过合理选择API,可平衡性能、安全与业务需求,实际开发中,推荐使用ThreadLocalRandom
作为默认方案,并在安全场景强制启用SecureRandom
。