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

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.原理

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

发布了141 篇原创文章 · 获赞 47 · 访问量 4万+

猜你喜欢

转载自blog.csdn.net/qq_41596568/article/details/104055163