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();
最佳实践
- 安全场景使用 SecureRandom:密码、令牌、密钥
- 高并发使用 ThreadLocalRandom:性能最好
- 一般场景使用 Random:简单易用
- 不要自己实现随机算法:使用标准库
总结
选择随机数生成器时,需要考虑安全性和性能。安全场景用 SecureRandom,高并发用 ThreadLocalRandom,一般场景用 Random。