播种Java Random时的奇怪行为

时间:2012-03-16 09:21:25

标签: java random

以下代码应创建两个具有相同种子的Random对象:

System.out.println("System time before: " + System.currentTimeMillis());
Random r1 = new Random();
Random r2 = new Random(System.currentTimeMillis());
System.out.println("System time after: " + System.currentTimeMillis());

System.out.println("r1: " + r1.nextInt());
System.out.println("r2: " + r2.nextInt());

种子应该是相同的,因为System.currentTimeMillis()在创建两个对象之前和之后没有改变,如输出所示:

System time before: 1331889186449
System time after: 1331889186449
r1: -1836225474
r2: 2070673752

从文档中,没有任何参数的构造函数只是:

public Random() { this(System.currentTimeMillis()); }

那是什么给出的?任何人都能解释为什么两个发电机应该有相同的种子时会返回不同的输出吗?

3 个答案:

答案 0 :(得分:7)

如果您使用的是java.util.Random,这是我看到的默认的no-args构造函数 - 现在它可能取决于您使用的JDK版本(此代码似乎用于sun JDK 6& 7至少):

public Random() {
    this(seedUniquifier() ^ System.nanoTime());
}

private static long seedUniquifier() {
    // L'Ecuyer, "Tables of Linear Congruential Generators of
    // Different Sizes and Good Lattice Structure", 1999
    for (;;) {
        long current = seedUniquifier.get();
        long next = current * 181783497276652981L;
        if (seedUniquifier.compareAndSet(current, next))
            return next;
    }
}

只是为了确认它,这里有一个代码来检查种子是否相同:

public static void main(String args[]) throws NoSuchFieldException, IllegalArgumentException, IllegalAccessException {
    System.out.println("System time before: " + System.currentTimeMillis());
    Random r1 = new Random();
    Random r2 = new Random(System.currentTimeMillis());
    System.out.println("System time after: " + System.currentTimeMillis());

    Field seed = Random.class.getDeclaredField("seed");
    seed.setAccessible(true);
    AtomicLong seed1 = (AtomicLong) seed.get(r1);
    AtomicLong seed2 = (AtomicLong) seed.get(r2);

    System.out.println("seed1 = " + seed1);
    System.out.println("seed2 = " + seed2);
}

答案 1 :(得分:2)

我认为默认构造函数不会按照你的说法执行(即public Random { this(System.currentTimeMillis()); } java文档只是说它正在初始化类,其值可能在每次调用时都不同{{ 3}}。查看Random(Mac OS X)实现中的标题

public Random() { this(++seedUniquifier + System.nanoTime()); }

答案 2 :(得分:0)

  

两个发电机应该有相同的种子时会返回不同的输出吗?

他们呢?在我看来,只有你的一台发电机才能获得毫米种子......