ThreadLocalRandom和random

先查看random 源码
1.有一个成员变量seed,类型为AtomicLong,无参构造方法,会通过特定的算法得到一个值 * 当前纳秒数得到一个seed。随机性就体现再这个当前纳秒数。算法计算的值是固定的。所以,如果指定seed值,那么产生的随机数就是一样的。
2.next每次生成随机数的算法都是固定的,没有掺杂随机因素。所以只要seed固定。每次调用next方法产生的随机数也是固定的。
3.random多线程并发下,使用的就是atomicLong 的的cas变化seed。所以,这里就有个缺点,多线程下,cas自旋消耗比较严重。


 public Random() {
        this(seedUniquifier() ^ System.nanoTime());
    }
 public Random(long seed) {
        if (getClass() == Random.class)
            this.seed = new AtomicLong(initialScramble(seed));
        else {
            // subclass might have overriden setSeed
            this.seed = new AtomicLong();
            setSeed(seed);
        }
    }
    private static final AtomicLong seedUniquifier
        = new AtomicLong(8682522807148012L);
 private static long seedUniquifier() {
    
        for (;;) {
            long current = seedUniquifier.get();
            long next = current * 181783497276652981L;
            if (seedUniquifier.compareAndSet(current, next))
                return next;
        }
    }
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));
    }

因为多线程下random自旋消耗比较大。所以有一个ThreadLocalRandom,顾名思义,和ThreadLocal原理差不多,线程本身维护自己的random(其实是random的seed),之后线程根据自己的seed产生随机数。自然就没有了多个线程自旋争夺同一个seed的并发消耗。

可以看到都是通过unsafe获取当前线程的当前变量值。

 public static ThreadLocalRandom current() {
       if (UNSAFE.getInt(Thread.currentThread(), PROBE) == 0)
           localInit();
       return instance;
   }

1.ThreadLocalRandom的随机性就体现在seeder这个atomicLong。第一次初始化的时候(也就是第一个调用current方法的线程),会通过当前毫秒数和当前纳秒数,获取到seed,之后每个线程调用一次current方法,都会通过old seed,通过特定的算法,获取到新seed,然后每个线程自己维护起来。
2.除了通过时间来达到随机效果之后。具体的算法和random也不一样,算法不研究。

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);
    }
    private static final AtomicLong seeder = new AtomicLong(initialSeed());
private static long initialSeed() {
        String pp = java.security.AccessController.doPrivileged(
                new sun.security.action.GetPropertyAction(
                        "java.util.secureRandomSeed"));
        if (pp != null && pp.equalsIgnoreCase("true")) {
            byte[] seedBytes = java.security.SecureRandom.getSeed(8);
            long s = (long)(seedBytes[0]) & 0xffL;
            for (int i = 1; i < 8; ++i)
                s = (s << 8) | ((long)(seedBytes[i]) & 0xffL);
            return s;
        }
        return (mix64(System.currentTimeMillis()) ^
                mix64(System.nanoTime()));
    }

你可能感兴趣的:(ThreadLocalRandom和random)