ThreadLocalRandom比Random快2–5倍,因它为每个线程维护独立种子、消除CAS竞争;必须每次调用current()获取实例,禁用static缓存、跨线程共享或手动计算范围。

直接用 ThreadLocalRandom.current() 获取实例再调用方法,别缓存、别共享、别手算范围——这是提升高并发随机数性能最核心的三件事。
为什么 Random 在多线程下会拖慢系统
Random 的 nextInt() 依赖一个全局 AtomicLong seed。多个线程同时更新它时,失败线程只能不断 CAS 自旋重试,不锁但空转耗 CPU。线程数超过 4 个,P99 延迟就容易翻倍;秒杀或发券这类高频场景,性能下降更明显。
ThreadLocalRandom 正确用法:每次取、局部存、范围明
它为每个线程维护独立种子,彻底避开竞争。但必须按规范使用:
-
不能 static 缓存:写成
private static final ThreadLocalRandom RANDOM = ThreadLocalRandom.current();是典型错误——所有线程共用初始化那一刻的单个实例,等于退化回 Random。 -
高频路径提前赋局部变量:在循环或热点方法里,先写
ThreadLocalRandom r = ThreadLocalRandom.current();,再反复调用r.nextInt(1, 101),避免重复查 ThreadLocal。 -
优先用双参范围方法:如
nextInt(1, 101)表达 [1, 100],语义清晰、无越界风险;别写nextInt(100) + 1,多一次运算还易错。
适用与不适用的边界要清楚
它适合“够随机就行”的场景:
立即学习“Java免费学习笔记(深入)”;
- 发券码、抽奖、ID 偏移、压测数据生成
- ForkJoinTask 中各子任务独立采样
不适合需要“可重现”的场景:
- 算法调试、游戏回放、单元测试(得用
new Random(seed)) - 跨线程协同生成同一随机序列(比如分布式哈希种子)
一句话总结关键点
每个线程玩自己的骰子,所以快;但你也永远拿不到别人摇出的同一个数字——这不是缺陷,是设计本意。只要不 static 化、不跨线程传、不手算偏移,就能稳稳发挥它的并发优势。



















