今天重构一段前人写的老代码的时候,看到for循环中本应完全随机的数值出现较高频率的相同,发现是new Random(System.currentTimeMillis())出现的问题
只需将
Random random =new Random(System.currentTimeMillis());
替换为更为简便的
Random random =new Random();
这样,问题就解决啦!
为什么会这样呢?
我们只需查看JDk的源码,就会发现原因其实很简单。
在使用new Random(System.currentTimeMillis())的时候,Random调用的是
public Random(long seed) {
if (getClass() == Random.class)
this.seed = new AtomicLong(initialScramble(seed));
else {
// subclass might have overriden setSeed
this.seed = new AtomicLong();
setSeed(seed);
}
}
而使用new Random(),则是调用的
public Random() {
this(seedUniquifier() ^ System.nanoTime());
}
我们在使用new Random(System.currentTimeMillis())的时候,会获取到当前系统毫秒级别的时间作为种子,那么在一些简单的循环中,就有可能得到相同的时间,这样就完全失去了随机性。
System.nanoTime()则是精确到微毫秒的系统计时器的当前值,值得注意的是,这个方法不可以用来获取系统当前时间,只能用作计时器,比如计算一段代码的运行耗时。
所以,想要使用完全随机数时,直接new Random()就好,就不要在传入其他东西啦