赞
踩
Random random = new Random();
System.out.println(random.nextInt(100));
一、奇怪的命名
public int nextInt(int bound) { if (bound <= 0) throw new IllegalArgumentException(BadBound); // 1.根据老的种子生成新的种子 int r = next(31); // 2.根据新的种子计算随机数 int m = bound - 1; if ((bound & m) == 0) // i.e., bound is a power of 2 r = (int)((bound * (long)r) >> 31); else { for (int u = r; u - (r = u % bound) + m < 0; u = next(31)) ; } return r; }
protected int next(int bits) {
long oldseed, nextseed;
AtomicLong seed = this.seed;
do {
oldseed = seed.get();
nextseed = (oldseed * multiplier + addend) & mask;
} while (!seed.compareAndSet(oldseed, nextseed));
return (int)(nextseed >>> (48 - bits));
}
剖析 next(int bits)方法
三、并发下
看起来一切很美好,其实不然,.使用CAS操作更新seed,在大量线程竞争的场景下,这个CAS操作很可能失败,失败了就会重试,而这个重试又会消耗CPU运算,从而使得性能大大下降了。
ThreadLocalRandom current = ThreadLocalRandom.current();
int num = current.nextInt(10);
current()
// 1.静态方法每次返回的对象都是同一个
// 2.如果当前线程的PROBE是0,说明是第一次调用current方法,那么需要调用localInit方法,否则直接返回已经产生的实例。
public static ThreadLocalRandom current() {
if (UNSAFE.getInt(Thread.currentThread(), PROBE) == 0)
localInit();
return instance;
}
localInit()
static final void localInit() {
int p = probeGenerator.addAndGet(PROBE_INCREMENT);
int probe = (p == 0) ? 1 : p; // skip 0
long seed = mix64(seeder.getAndAdd(SEEDER_INCREMENT));
Thread t = Thread.currentThread();
UNSAFE.putLong(t, SEED, seed);
UNSAFE.putInt(t, PROBE, probe);
}
current.nextInt();
public int nextInt(int bound) {
if (bound <= 0)
throw new IllegalArgumentException(BadBound);
int r = mix32(nextSeed());
int m = bound - 1;
if ((bound & m) == 0) // power of two
r &= m;
else { // reject over-represented candidates
for (int u = r >>> 1;
u + m - (r = u % bound) < 0;
u = mix32(nextSeed()) >>> 1)
;
}
return r;
}
nextSeed()
和Random类下的nextXXX方法的原理一样,也是根据旧的种子生成新的种子,然后根据新的种子来生成随机数
final long nextSeed() {
Thread t; long r; // read and update per-thread seed
UNSAFE.putLong(t = Thread.currentThread(), SEED,
r = UNSAFE.getLong(t, SEED) + GAMMA);
return r;
}
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。