你在项目中是否这样生成过随机数?
// 场景 1:静态实例
private static Random random = new Random();// 场景 2:每次 new 一个
int value = new Random().nextInt(100);// 场景 3:多线程环境下共享
public class UserService {private Random random = new Random();public String generateToken() {return "token-" + random.nextInt(1000000);}
}
这些写法看似正常,实则暗藏性能瓶颈与安全风险!
陷阱一:new Random()
的代价
// 错误示范
for (int i = 0; i < 10000; i++) {int r = new Random().nextInt(100);
}
问题:
new Random()
会尝试读取系统熵源(如/dev/random
)来初始化种子- 在低熵环境(如 Docker、云服务器)下,可能阻塞数秒甚至更久
- 频繁创建实例导致性能急剧下降
✅ 解决方案:复用实例
陷阱二:多线程下的性能悬崖
ExecutorService executor = Executors.newFixedThreadPool(10);
Random random = new Random();// 10 个线程并发调用
IntStream.range(0, 10000).forEach(i ->executor.submit(() -> random.nextInt(100))
);
问题:
- 多线程竞争
AtomicLong seed
CAS
失败率高 → 大量线程自旋重试- 性能可能下降 10 倍以上
安全敏感场景:必须用 SecureRandom
// 生成 Token、密钥、Salt 等
SecureRandom secureRandom = new SecureRandom();
byte[] salt = new byte[16];
secureRandom.nextBytes(salt);
特点:
- 基于强熵源(操作系统随机数)
- 生成的随机数不可预测
- 性能较低,但安全
✅ 永远不要用
Random
生成密码、Token、密钥!
性能对比(100万次调用,8线程)
方式 | 耗时(ms) | 吞吐量(ops/s) |
| 12,500 | 80,000 |
| 8,200 | 122,000 |
| 180 | 5,555,000 |
| 3,800 | 263,000 |
🔥
ThreadLocalRandom
性能是共享Random
的 45 倍!
🔥 “高并发用 ThreadLocalRandom
,安全用 SecureRandom
,其他情况避免 new Random()
!”
正确姿势:静态 Random
实例(单线程或低并发)
private static final Random RANDOM = new Random();public int getRandom() {return RANDOM.nextInt(100);
}
✅ 适用于:低频调用、工具类、非关键路径