播种Java Random时的奇怪行为 [英] Weird behaviour when seeding Java Random

查看:85
本文介绍了播种Java Random时的奇怪行为的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

The following code should create two Random objects with identical seeds:

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()在创建两个对象之前和之后没有改变,如输出所示:

The seeds should be identical since System.currentTimeMillis() did not change before and after creating the two objects as shown in the output:

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

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

From the docs, the constructor without any arguments is simply:

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

那是什么给出的?任何人都可以解释为什么当两个生成器应该有相同的种子时返回不同的输出?

So what gives? Can anyone explain why the two generators return different outputs when they should have the same seed?

推荐答案

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

If you are using java.util.Random, this is the default no-args constructor I see - now it might depend on the version of JDK you are using (this code seems to be used for sun JDK 6 & 7 at least):

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;
    }
}

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

And just to confirm it, here is a code to check if the seeds are identical:

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);
}

这篇关于播种Java Random时的奇怪行为的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆