ThreadLocalRandom 是线程绑定的随机数生成器,非 Random 子类、无 public 构造方法,必须通过 current() 获取当前线程实例;不支持 seed 设置,不可复现序列;所有 nextXxx 方法需显式指定范围,如 nextInt(10) 返回 [0,10)。

ThreadLocalRandom 是什么,为什么不能直接替换 Random
它不是 Random 的子类,也没有 public 构造方法,不能 new 出来,也不能用 new ThreadLocalRandom()。它是线程绑定的单例,每次调用 current() 都返回当前线程专属实例——这点和 ThreadLocal<random></random> 表面相似,但底层完全不共享状态,也无需初始化开销。
常见错误是写成:ThreadLocalRandom rand = new ThreadLocalRandom(),编译直接报错;或者试图在静态上下文里缓存 ThreadLocalRandom.current() 结果,导致多线程下取到同一个实例,失去线程隔离性。
- 必须每次需要时都调用
ThreadLocalRandom.current(),不要缓存返回值 - 它不支持设置 seed,所以无法复现随机序列(测试时要注意)
- 不能用于需要跨线程传递“同一随机流”的场景,比如分片一致性哈希预生成种子
怎么生成 int/long/double 范围内的随机数
ThreadLocalRandom 没有 nextInt() 无参重载,所有生成方法都要求显式指定范围,避免意外溢出或边界误解。例如 nextInt(10) 返回的是 [0, 10),不是 [0, 10];而 nextInt(5, 10) 才是 [5, 10)。
对比 Random:后者 nextInt(10) 同样是 [0,10),但开发者常误以为是闭区间;ThreadLocalRandom 强制你写清楚上下界,反而降低了出错概率。
立即学习“Java免费学习笔记(深入)”;
-
nextInt(int bound)→ [0, bound) -
nextInt(int origin, int bound)→ [origin, bound),且必须 origin -
nextLong(long origin, long bound)和nextDouble(double origin, double bound)同理 - 如果只需要布尔值,用
nextBoolean(),比nextInt(2) == 0更清晰、稍快
高并发下性能差异到底在哪
Random 内部用一个 AtomicLong 维护 seed,每次 next() 都要 CAS 更新,竞争激烈时大量线程自旋失败;而 ThreadLocalRandom 每个线程用自己栈上的 long 变量存 seed,无共享、无同步,吞吐量通常高出 3–5 倍(视 CPU 核心数和争用程度而定)。
但别为了“高并发”盲目替换:如果只是单线程批量生成、或每秒调用不到几十次,性能差异几乎不可测,反而因缺少 seed 控制增加调试难度。
- 适合场景:请求级随机(如限流采样)、批处理分片、游戏逻辑帧内扰动
- 不适合场景:单元测试中需要固定随机序列、加密相关伪随机(它不安全)、低频且需可重现的配置随机化
- 注意 JVM 参数
-XX:+UseThreadLocalHandshakes(JDK 10+)对它的间接影响很小,不用特意调
和 SecureRandom、SplittableRandom 怎么选
ThreadLocalRandom 不提供密码学安全性,也不支持 fork/join 分支生成独立子流——这是 SecureRandom 和 SplittableRandom 的分工。
典型误用是拿它生成 token 或 salt,结果被预测攻击;或者想在 parallelStream 里每个分支用不同随机源,却只写了 ThreadLocalRandom.current().nextInt(),其实所有分支仍共享同一线程的实例(parallelStream 的 worker 线程是复用的,但每个 task 运行在线程池线程上,current() 仍是正确的)。
- 要密码学安全 → 用
SecureRandom,接受性能代价 - 要做并行计算且各分支需独立可重现随机流 → 用
SplittableRandom,配合split() - 只是普通业务逻辑里的高并发随机 →
ThreadLocalRandom.current()是最轻量、最直接的选择
真正容易被忽略的是:它和线程生命周期强绑定。线程池中长期存活的线程,其 ThreadLocalRandom 实例会一直存在,seed 会持续更新——这本身没问题,但如果你在 shutdown 线程池前没做任何事,也没关系;它不会泄漏资源,也不需要手动清理。










