java Random() 如何找到种子?

How does java Random() find a seed?

从我的研究来看,每个人似乎都说 java random 在未指定时使用以毫秒为单位的系统时间作为其默认种子。因此,如果我们在生成随机数时有系统时间,那么我们应该能够知道生成该数字的种子是什么。 所以,

(new Random()).nextLong;
long time = System.currentTimeMillis();
(new Random(time)).nextLong

应该会产生两个相同的数字,因为种子是一样的,对吧?它不是这样的,要么它没有使用 TimeMillis 作为种子,要么我做错了其他事情。

非常感谢您的帮助,我已经搜索了几个小时,但似乎找不到一致的答案。我只想确切地知道在未指定种子时它是如何找到种子的。我的想法是它可能确实使用了系统时间,但在成为最终种子之前它会乘以它等等。

再次感谢:)

Java用于使用系统时间作为默认种子,最高1.4.2。在 1.5 中,这个“错误”被修复了。比较 1.4.2 API specification:

Creates a new random number generator. Its seed is initialized to a value based on the current time:

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

Two Random objects created within the same millisecond will have the same sequence of random numbers.

1.5 API specification:

Creates a new random number generator. This constructor sets the seed of the random number generator to a value very likely to be distinct from any other invocation of this constructor.

OpenJDK 中的当前实现使用静态 AtomicLong,它会在您每次创建没有种子的新 Random 实例时更新。如果本地没有源码,可以在source code on github:

中找到
    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 * 1181783497276652981L;
            if (seedUniquifier.compareAndSet(current, next))
                return next;
        }
    }

    private static final AtomicLong seedUniquifier
        = new AtomicLong(8682522807148012L);