#多线程环境下生成随机数

http://www.importnew.com/12460.html

http://www.maocaoying.com/view/217

Java里有伪随机型和安全型两种随机数生成器。伪随机生成器根据特定公式将seed转换成新的伪随机数据的一部分。安全随机生成器在底层依赖到操作系统提供的随机事件来生成数据。

安全随机生成器

  • 需要生成加密性强的随机数据的时候才用它;
  • 生成速度慢;
  • 如果需要生成(Linux /dev/random 就是个这样的安全随机生成器)大量随机数据,可能会产生堵塞需要等待外部中断事件。

而伪随机生成器,只依赖于”seed”的初始值。如果你给生成算法提供相同的seed,可以得到一样的伪随机序列。一般情况下,由于它是计算密集型的(不依赖于任何IO设备),因此生成速度更快。接下来,我们将回顾伪随机生成器的进化史。

#java.util.Random

java.util.Random 从Java 1.0开始就存在了。它是一个线程安全类,理论上可以通过它同时在多个线程中获得互不相同的随机数。这样的线程安全是通过_AtomicLong_实现的。

Random 使用 AtomicLong CAS (compare-and-set)操作来更新它的seed,尽管很多非阻塞式算法中使用了非阻塞式原语,CAS在资源高度竞争时的表现依然糟糕。在后面的测试结果中你可以看到它的糟糕表现。

#java.util.concurrent.ThreadLocalRandom

Java 7增加了_java.util.concurrent.ThreadLocalRandom_ 并企图将它与 java.util.Random 结合以克服所有的性能问题。ThreadLocalRandom类继承自_java.util.Random_。

ThreadLocalRandom 的主要实现细节:

  • 它使用一个普通的 long 而不是使用 Random 中的 AtomicLong 作为seed。
  • 你不能自己创建_ThreadLocalRandom_实例,因为它的构造函数没有设置为public。可以使用它的静态工厂_ThreadLocalRandom.current(),这个工厂方法调用了内置的_ThreadLocal< ThreadLocalRandom>
  • 它是CPU缓存感知式的,使用8个 long 虚拟域来填充64位L1高速缓存行。

所有这些改变都是很重要的,在接下来的测试中你将会感受到。

#测试

我们将进行下面5种测试:

  1. 一个单独的_java.util.Random_被N个线程共享
  2. ThreadLocal< Random>
  3. java.util.concurrent.ThreadLocalRandom
  4. java.util.Random[],其中每个线程N使用一个数组下标为N的_Random_。
  5. java.util.Random[],其中每个线程N使用一个数组下标为N * 2的_Random_。

http://www.importnew.com/12460.html

补充: https://blog.csdn.net/wangyunpeng0319/article/details/78903541

讲解了Random的实现原理以及介绍了Random在多线程下存在竞争种子原子变量更新操作失败后自旋等待的缺点,从而引出ThreadLocalRandom类,ThreadLocalRandom使用ThreadLocal的原理,让每个线程内持有一个本地的种子变量,该种子变量只有在使用随机数时候才会被初始化,多线程下计算新种子时候是根据自己线程内维护的种子变量进行更新,从而避免了竞争,

ps: 这里说的竞争,应该是共有一个new random()变量. 每次函数都new的话,应为多线程问题,会都差不多一样的种子. 随机值长一样....