ThreadLocalRandom类
Posted wqff-biubiu
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ThreadLocalRandom类相关的知识,希望对你有一定的参考价值。
一、Random类
public class RandomTest { public static void main(String[] args){ Random random = new Random(); for (int i = 0; i < 10; i++){ System.out.println(random.nextInt()); } } } /* * nextInt() 源码 */ 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));//获取nextseed采用CAS保证原子性,多线程会使大量线程进行自旋重试,降低了并发性能。 return (int)(nextseed >>> (48 - bits)); }
二、ThreadLocalRandom类
继承了Random重写了nextInt,类似于ThreadLocal的实现,在各自Thread实例中保存自己的seed,具体声明源码如下。
// The following three initially uninitialized fields are exclusively // managed by class java.util.concurrent.ThreadLocalRandom. These // fields are used to build the high-performance PRNGs in the // concurrent code, and we can not risk accidental false sharing. // Hence, the fields are isolated with @Contended. /** The current seed for a ThreadLocalRandom */ @sun.misc.Contended("tlr") long threadLocalRandomSeed; /** Probe hash value; nonzero if threadLocalRandomSeed initialized */ @sun.misc.Contended("tlr") int threadLocalRandomProbe; /** Secondary seed isolated from public ThreadLocalRandom sequence */ @sun.misc.Contended("tlr") int threadLocalRandomSecondarySeed;
ThreadLocalRandom实现
public class ThreadLocalRandomTest { public static void main(String[] args){ ThreadLocalRandom random = ThreadLocalRandom.current(); for (int i = 0;i < 10; i++){ System.out.println(random.nextInt(5)); } } } /** * nextseed获取源自各自线程中保存的seed,实现了线程隔离 */ 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);//Thread.currentThread.threadLocalRandomSeed return r; }
ThreadLocalRandom主要源码模块
1.unsafe初始化
// Unsafe mechanics private static final sun.misc.Unsafe UNSAFE; private static final long SEED; private static final long PROBE; private static final long SECONDARY; static { try { UNSAFE = sun.misc.Unsafe.getUnsafe(); Class<?> tk = Thread.class; SEED = UNSAFE.objectFieldOffset(tk.getDeclaredField("threadLocalRandomSeed")); PROBE = UNSAFE.objectFieldOffset(tk.getDeclaredField("threadLocalRandomProbe")); SECONDARY = UNSAFE.objectFieldOffset(tk.getDeclaredField("threadLocalRandomSecondarySeed")); } catch (Exception e) { throw new Error(e); } }
2.构造方法私有化,提供静态方法current实例化,保证单例
/** Constructor used only for static singleton */ private ThreadLocalRandom() { initialized = true; // false during super() call } /** * Returns the current thread‘s {@code ThreadLocalRandom}.*/ public static ThreadLocalRandom current() { if (UNSAFE.getInt(Thread.currentThread(), PROBE) == 0)//当前线程Thread实例中threadLocalRandomProbe为0初始化seed localInit(); return instance; } /** * Initialize Thread fields for the current thread. Called only * when Thread.threadLocalRandomProbe is zero, indicating that a * thread local seed value needs to be generated. Note that even * though the initialization is purely thread-local, we need to * rely on (static) atomic generators to initialize the values. */ static final void localInit() { int p = probeGenerator.addAndGet(PROBE_INCREMENT); int probe = (p == 0) ? 1 : p; // 不为0,保证单例 long seed = mix64(seeder.getAndAdd(SEEDER_INCREMENT)); Thread t = Thread.currentThread(); UNSAFE.putLong(t, SEED, seed);//存到当前线程的threadLocalRandomSeed中 UNSAFE.putInt(t, PROBE, probe);// }
3.随机数
/** * Returns a pseudorandom {@code int} value between zero (inclusive) * and the specified bound (exclusive). * * @param bound the upper bound (exclusive). Must be positive. * @return a pseudorandom {@code int} value between zero * (inclusive) and the bound (exclusive) * @throws IllegalArgumentException if {@code bound} is not positive */ public int nextInt(int bound) { if (bound <= 0) throw new IllegalArgumentException(BadBound); int r = mix32(nextSeed());//重点下一个seed 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; } 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);//取得是当前线程中的threadLocalRandomSeed变量 return r; }
以上是关于ThreadLocalRandom类的主要内容,如果未能解决你的问题,请参考以下文章
还在用 Random?试试 ThreadLocalRandom,好用!
还在用 Random生成随机数了?试试 ThreadLocalRandom,好用!