Java Math.random()的种子是什么时候?

Java Math.random()的种子是什么时候?,java,random,thread-safety,Java,Random,Thread Safety,根据文件: 当第一次调用此方法时,它会创建一个新的伪随机数生成器,就像表达式一样 new java.util.Random 此后,这个新的伪随机数生成器将用于此方法的所有调用,并且不会在其他任何地方使用 我对“首次调用此方法的时间”的范围感到困惑-是在我的应用程序首次调用它的时间吗?无论我的应用程序做什么,它是否只进行过一次种子设定?查看源代码,Math.random()的相关代码定义为: private static Random randomNumberGenerator; privat

根据文件:

当第一次调用此方法时,它会创建一个新的伪随机数生成器,就像表达式一样

new java.util.Random
此后,这个新的伪随机数生成器将用于此方法的所有调用,并且不会在其他任何地方使用


我对“首次调用此方法的时间”的范围感到困惑-是在我的应用程序首次调用它的时间吗?无论我的应用程序做什么,它是否只进行过一次种子设定?

查看源代码,
Math.random()
的相关代码定义为:

private static Random randomNumberGenerator;

private static synchronized void initRNG() {
    if (randomNumberGenerator == null) 
        randomNumberGenerator = new Random();
}

public static double random() {
    if (randomNumberGenerator == null) initRNG();
    return randomNumberGenerator.nextDouble();
}

因此,由于
randomNumberGenerator
是一个
静态
变量,一旦JVM中的任何类调用它来初始化它(第一次调用
Math.random()
),它就会停留在那里(除非不再需要并卸载该类。

当方法
Math.random()时,它会被初始化)第一次调用

有趣的是,在Java5和Java6中,代码使用了,所以它不是线程安全的,即使看起来是这样

[EDIT]正确的代码如下所示:

private static volatile Random randomNumberGenerator; // broken without volatile
或者,但更昂贵:

public static synchronized double random() {
    ...
}

[EDIT2]官方错误:

当它第一次在JVM中被调用时(通过任何代码)

它正在执行以下操作(不安全-请参阅下面的链接):

致电:

private static synchronized void initRNG() {
    if (randomNumberGenerator == null) 
        randomNumberGenerator = new Random();
}

编辑请注意,此代码不是线程安全的。官方错误:

@SanjayT.Sharma:您的两条语句都不正确。同步块不会阻止引用在实例完全初始化之前变为非空(因此下一次调用可以接收半工作实例)根据Joshua Bloch的说法,双重检查锁定在Java 7中仍然是一种坏模式,他应该知道这些事情。有关详细信息,请参阅。如果
randomNumberGenerator
volatile
(这是Java 5中的修复程序),它将起作用我的错,把事情搞混了。+1-1因为没有提到这段代码不是线程安全的。没问题,但你能详细解释第一句话来解释其他应用程序会使用相同的JVM吗?@Andrew:applications/web应用程序服务器,如Tomcat、JBoss或WebSphere,允许在同一个VM中安装多个应用程序。@Aaron Digulla Gee。…这有点苛刻。但可以肯定的是,它是在
volatile
关键字之前编写的。@Andrew应用程序中的任何代码或应用程序调用的任何代码-可能是JDK中的代码,在您正在使用的某个实现中被深层调用。
private static synchronized void initRNG() {
    if (randomNumberGenerator == null) 
        randomNumberGenerator = new Random();
}