你在项目中是否这样生成过随机数?

// 场景 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)

new Random()

12,500

80,000

Random 共享

8,200

122,000

ThreadLocalRandom

180

5,555,000

SecureRandom

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);
}

适用于:低频调用、工具类、非关键路径