Java_语法基础_不要随便设置随机种子

随机数在太多的地方使用了,比如加密、混淆数据等,我们使用随机数是期望获得一个唯一的、不可仿造的数字,以避免产生相同的业务数据造成混乱。在Java项目中通常是通过Math.random方法和Random类来获得随机数的,我们来看一段代码:

package deep;

import java.util.Random;

public class Client {

    public static void main(String[] args) {
        Random r = new Random();
        for (int i = 1; i < 4; i++) {
            System.out.println("第" + i + "次:" + r.nextInt());
        }
    }

}

代码很简单,我们一般都是这样获得随机数的,运行此程序可知:三次打印的随机数都不相同,即使多次运行结果也不同,这也正是我们想要随机数的原因。我们再来看下面的程序:

package deep;

import java.util.Random;

public class Client {

    public static void main(String[] args) {
        Random r = new Random(1000);
        for (int i = 1; i < 4; i++) {
            System.out.println("第" + i + "次:" + r.nextInt());
        }
    }

}

运行结果:
第1次:-1244746321
第2次:1060493871
第3次:-1826063944

上面使用了Random的有参构造,计算机不同输出的随机数也不同,但是有一点是相同的:在同一台机器上,甭(beng)管运行多少次,所打印的随机数都是相同的,也就是说第一次运行,会打印出这三个随机数,第二次运行还是打印出这三个随机数,只要是在同一台硬件机器上,就永远会打印出相同的随机数,似乎随机数不随机了,问题何在?
那是因为产生随机数的种子被固定了,在Java中,随机数的产生取决于种子,随机数和种子之间的关系遵从以下两个规则:

  • 种子不同,产生不同的随机数
  • 种子相同,即使实例不同也产生相同的随机数

看完上面两个规则,我们再来看这个例子,会发现问题就出在有参构造上,Random类的默认种子(无参构造)是System.nanoTime()的返回值(JDK1.5以前默认种子是System.currentTimeMills()的返回值),注意这个值是距离某一个固定时间点的纳秒数,不同的操作系统和硬件有不同的固定时间点,也就是说不同的操作系统其纳秒值是不同的,而同一个操作系统纳秒值也会不同,随机数自然也就不同了。
new Random(1000)显式地设置了随机种子为1000,运行多次,虽然实例不同,但都会获得相同的三个随机数。所以,除非必要,否则不要设置随机种子。
顺便提一下,在Java中有两种方法可以获得不同的随机数:通过java.util.Random类获得随机数的原来和Math.random方法相同,Math.random方法也是通过生成一个Random类的实例,然后委托nextDouble方法的,两者是殊途同归,没有差别。

以下为Math.random方法的解释:
random
public static double random()返回带正号的 double 值,该值大于等于 0.0 且小于 1.0。返回值是一个伪随机选择的数,在该范围内(近似)均匀分布。
第一次调用该方法时,它将创建一个新的伪随机数生成器,与以下表达式完全相同
new java.util.Random
之后,新的伪随机数生成器可用于此方法的所有调用,但不能用于其他地方。
此方法是完全同步的,可允许多个线程使用而不出现错误。但是,如果许多线程需要以极高的速率生成伪随机数,那么这可能会减少每个线程对拥有自己伪随机数生成器的争用。

返回:
大于等于 0.0 且小于 1.0 的伪随机 double 值。
另请参见:
Random.nextDouble()

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值