这是一个随机数生成器,而我们比较常用的是Random类,但是它是有一定的局限性。首先看一下Random生成随机数过程
Random类实现及局限
我们常用的一个方法是Random.nextInt()
,那就以它作为例子:
public int nextInt (int bound) {
if (bound <= 0)
throw new IllealArgumentException(BadBound);
//(1)根据老种子生成新种子
int r = next(31);
//根据新种子计算随机数
...
return r;
}
总结为两个步骤:
- 首先根据老种子生成新种子
- 根据新种子计算新的随机数
此处最关键的就是生成新种子的过程,因为根据种子生成随机数的算法是固定的。若多个线程都获得了同一个老种子,那么多个线程就会生成同一个新种子,也就会生成同样的随机数。因此要保证代码(1)的原子性,只有一个线程能够根据旧的种子获得新种子,那样其他线程就会丢掉自己获得的老种子而使用上一个线程的新种子来计算自己的新种子。Random函数使用了一个原子变量达到了这个效果。看一下next()的代码:
protected int next(int bits) {
long oldseed, nextseed;
AtomicLong seed = this.seed;
do {
oldseed = seed.get(); //获得旧的seed
nextseed = (oldseed * multiplier