② 实现原理
ThreadLocalRandom 的实现原理和 ThreadLocal 类似,它是让每个线程持有自己的本地种子,该种子在生成随机数时候才会被初始化,实现源码如下:
public int nextInt(int bound) { // 参数效验 if (bound <= 0) thrownew IllegalArgumentException(BadBound); // 根据当前线程中种子计算新种子 int r = mix32(nextSeed()); int m = bound - 1; // 根据新种子和 bound 计算随机数 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 // 获取当前线程中 threadLocalRandomSeed 变量,然后在种子的基础上累加 GAMMA 值作为新种子 // 再使用 UNSAFE.putLong 将新种子存放到当前线程的 threadLocalRandomSeed 变量中 UNSAFE.putLong(t = Thread.currentThread(), SEED, r = UNSAFE.getLong(t, SEED) + GAMMA); return r; }
③ 优缺点分析
ThreadLocalRandom 结合了 Random 和 ThreadLocal 类,并被隔离在当前线程中。因此它通过避免竞争操作种子数,从而在多线程运行的环境中实现了更好的性能,而且也保证了它的线程安全。
另外,不同于 Random, ThreadLocalRandom 明确不支持设置随机种子。它重写了 Random 的setSeed(long seed)
方法并直接抛出了 UnsupportedOperationException
异常,因此降低了多个线程出现随机数重复的可能性。
源码如下:
public void setSeed(long seed) { // only allow call from super() constructor if (initialized) thrownew UnsupportedOperationException(); }
只要程序中调用了 setSeed() 方法就会抛出 UnsupportedOperationException
异常,如下图所示: