今天要说的 ThreadLocalRandom
是Java7引入的随机数生成器, 在此之前我们生成随机数都是使用
- 创建
java.util.Random
实例 - 使用Math.random(), 其实内部也是创建了一个
java.util.Random
使用Random没有问题, 其seed使用AtomicLong来存储, 在多线程下也是线程安全的.
但是, 如果在多线程下使用Random, 会导致多线程的竞争开销, 也会降低Random的随机性, 于是便有了ThreadLocalRandom
.
ThreadLocalRandom
那么, 对于前面的问题, ThreadLocalRandom
对这些做了哪些工作呢 ?
假设使用以下代码获取随机数 :
int randomInt = ThreadLocalRandom.current().nextInt(); |
ThreadLocalRandom.current()
:
我们来看一下ThreadLocalRandom
的内部实现:
public static ThreadLocalRandom current() { |
其中, SEED
和PROBE
可以参考下面定义:
Class<?> tk = Thread.class; |
Thread.java
@sun.misc.Contended("tlr") |
UNSAFE.getInt(Thread.currentThread(), PROBE)
就是获取Thread
对象中offset偏移地址对应的field threadLocalRandomProbe
的值, threadLocalRandomProbe
是nonzero if threadLocalRandomSeed initialized
.
所以, 如果PROBE
值为零, 将进行localInit(), 当前Thread对象的threadLocalRandomSeed 和 threadLocalRandomProbe将会被赋值. (`@sun.misc.Contended("tlr")`是为了解决伪共享的问题, 将另起一篇博客介绍)
nextInt()
public int nextInt() { |
注意:
SEED
是field的偏移量GAMMA
是seed的increment
这里会更新当前Thread的SEED, 最终mix32()生成int随机数.
最后
从上可知ThreadLocalRandom
的工作方式, 它为每个线程分配了一个SEED(被Thread对象持有), 故而减少了多线程下的竞争开销, 也使随机性更加好.