我知道如果我使用Java中的随机生成器,使用nextInt生成数字,那么这些数字将是均匀分布的。但是如果我使用两个Random实例,使用这两个Random类生成数字,这些数字是否仍然是均匀分布的呢?
Random
实例生成的数字都是均匀分布的,因此,如果将两个Random
实例生成的随机数序列组合起来,它们也应该是均匀分布的。java.util.Random
的源代码中可以看到:private static volatile long seedUniquifier = 8682522807148012L;
public Random() { this(++seedUniquifier + System.nanoTime()); }
如果您通过使用Random(long seed)
构造函数或调用setSeed(long seed)
来显式设置种子,则需要自行处理此问题。一个可能的方法是使用随机数生成器为所有其他生成器生成种子。
如果您使用相同的值来初始化两个Random实例,那么您肯定不能获得高质量的离散均匀分布。考虑最基本的情况,它会打印出完全相同的数字两次(没有比这更不随机的了...):
public class RngTest2 {
public static void main(String[] args) throws Exception {
long currentTime = System.currentTimeMillis();
Random r1 = new Random(currentTime);
Random r2 = new Random(currentTime);
System.out.println(r1.nextInt());
System.out.println(r2.nextInt());
}
}
long
都是原子的,无论你是否将其标记为volatile
(这意味着您永远不会看到半写入的值)。但是不是原子的(再次无论volatile
如何)是读取和增量和写入长整型变量。因此,多个线程都可以将变量读取为0
(例如),所有线程都将该值增加到1
,并且所有线程都将1
写回变量。为确保每次访问计数器100%可靠地递增,您需要同步。java.util.concurrent.atomic
中的类(如AtomicLong
)使此过程变得简单且正确。 - Mike Clark