java 使用当前时间与不使用随机数生成器

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/32277110/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-02 19:56:39  来源:igfitidea点击:

Using Random Number Generator with Current Time vs Without

javarandom

提问by ayePete

I want to understand what the difference is between using a Random number generator with System.currentTimeMillis()as the seed and just using the default constructor. That is, what is the difference between this:

我想了解使用随机数生成器System.currentTimeMillis()作为种子与仅使用默认构造函数之间的区别。也就是说,这有什么区别:

Random rand = new Random(System.currentTimeMillis());

and this:

还有这个:

Random rand = new Random();

I know that the numbers are pseudo-random, but I am yet to fully understand the details, and how they come about, between the level of 'randomness' one gets when current time is used as seed, and when the default constructor is used.

我知道这些数字是伪随机的,但我还没有完全理解细节,以及它们是如何产生的,在使用当前时间作为种子时获得的“随机性”级别与使用默认构造函数时.

采纳答案by Josep Valls

If you want your random sequences to be the same between runs you can specify a seed. Usually you don't want that to happen so you use a different seed for every run and System.currentTimeMillis() is reasonable seed commonly used. If you are facing something multithreded where multiple threads will initialize the RNG at the same time you may want to avoid using System.currentTimeMillis() and let Java use its own initialization.

如果您希望运行之间的随机序列相同,您可以指定一个种子。通常您不希望这种情况发生,因此每次运行都使用不同的种子,而 System.currentTimeMillis() 是常用的合理种子。如果您面临着多线程同时初始化 RNG 的情况,您可能希望避免使用 System.currentTimeMillis() 并让 Java 使用自己的初始化。

回答by Ted Hopp

Supplying your own seed is useful for simulations where you purposely want to generate the same sequence of pseudorandom values multiple times. In general, though, it's just as well to use the default constructor.

提供您自己的种子对于您有意多次生成相同伪随机值序列的模拟很有用。不过,一般来说,使用默认构造函数也一样好。

When the default constructor is used, the docssay:

当使用默认构造函数时,文档说:

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.

此构造函数将随机数生成器的种子设置为一个很可能与此构造函数的任何其他调用不同的值。

In other words, it generates its own seed internally. The details depend on the particular Java implementation being used. One implementation I've seen has this:

换句话说,它在内部生成自己的种子。详细信息取决于所使用的特定 Java 实现。我见过的一个实现是这样的:

private static volatile long seedBase = 0;

public Random() {
    setSeed(System.nanoTime() + seedBase);
    ++seedBase;
}

The actual quality of the randomness doesn't change. If the quality of the random sequence is of concern to you, you can also use java.security.SecureRandom, which has better cryptographic behavior. (See, e.g., this thread.)

随机性的实际质量不会改变。如果您关心随机序列的质量,您也可以使用java.security.SecureRandom,它具有更好的加密行为。(参见,例如,这个线程。)

回答by Jan Schaefer

If you look into the implementation of the default constructor of Random, you can see that it uses System.nanoTime()internally. In addition, it uses a seed 'uniquifier' to make subsequent seeds even more distinct. This, however, requires access to a static final AtomicLong. Thus if you have a highly concurrent application where many threads are constructing Randominstances, it might be better to not use the default constructor to avoid contention on the seed generation. If you want to guarantee that two threads can never get the same seed you should take the default constructor. This said, in practice, in 99% of the cases, it will be irrelevant which variant you take.

如果您查看 的默认构造函数的实现Random,您会发现它在System.nanoTime()内部使用。此外,它使用种子“唯一标识符”使后续种子更加清晰。但是,这需要访问static final AtomicLong. 因此,如果您有一个高度并发的应用程序,其中许多线程正在构造Random实例,最好不要使用默认构造函数来避免对种子生成的争用。如果你想保证两个线程永远不会得到相同的种子,你应该采用默认构造函数。这就是说,在实践中,在 99% 的情况下,您采用哪种变体都无关紧要。

As Ted Hopp correctly states, the behavior of the default constructor depends on the concrete JDK implementation and also varies between Java versions.

正如 Ted Hopp 正确指出的那样,默认构造函数的行为取决于具体的 JDK 实现,并且在 Java 版本之间也有所不同。

Also see Contention in concurrent use of java.util.Randomfor another contention issue with the Randomclass.

另请参阅同时使用 java.util.Random的争用以了解Random该类的另一个争用问题。