Java并发编程--ThreadLocalRandom类原理剖析

淡淡的烟草味﹌ 2023-07-01 08:53 112阅读 0赞

文章目录

    1. Random类及其局限性
    1. ThreadLocalRandom
    1. 源码分析
      • (1). ThreadLocalRandom current()方法
      • (2). int nextInt(int bound)方法
  • 4.原理

1. Random类及其局限性

 Random生成随机数需要一个默认的种子,是一个long类型的数字.

生成新的随机数需要两个步骤:

  • 现根据老的种子生成新的种子
  • 根据新的种子来计算新的随机数

 由于每个线程都共享一个种子.而由种子计算随机数的算法是通用的,那么在多线程下多个线程就可能会生成一样的随机数(老种子相同导致新种子相同 ),.所以这里会使用CAS操作以保证对种子的操作的原子性.

 但是CAS操作会造成大量线程的自旋重试,降低并发性能.

2. ThreadLocalRandom

 为了弥补多线程高并发情况下Random的缺陷,新增了ThreadLocalRandom类.

 在ThreadLocalRandom类中,每个线程都维护一个(自己的)种子变量,每个线程的计算都是互不干扰的.

3. 源码分析

 ThreadLocalRandom类集成了Random类,类图结构如下
在这里插入图片描述

 ThreadLocalRandom中每个线程的种子存放在集体调用线程的threadLocalRandomSeed中,ThreadLocalRandom类只是个工具类.threadLocalRandomSeed变量就是Thread类中的一个普通long变量,不是原子变量(不需要这样设置,这个变量本身就是线程级别的).

 线程获取ThreadLocalRandom实例时,获取的是同一个实例,具体的种子存放在线程中,实例中只包含与线程无关的通用算法,所以是线程安全的.

(1). ThreadLocalRandom current()方法

 获取ThreadLocalRandom实例,并初始化调用线程中的threadLocalRandomSeed和threadLocalRandomProbe变量.(在不使用随机数功能时,不会初始化Thread类中的种子变量)

(2). int nextInt(int bound)方法

 计算当前线程的下一个随机数

4.原理

 让每个线程都持有一个本地的种子变量,该种子变量只有在使用随机数时才会被初始化。在多线程下计算新种子时,是根据自己线程内维护的种子变量进行更新,从而避免了竞争

发表评论

表情:
评论列表 (有 0 条评论,112人围观)

还没有评论,来说两句吧...

相关阅读