在 Java 中,相对于简单的算术运算,Math.random() 生成一个数字需要多长时间?我正在尝试随机分布 ArrayList 中的对象,该对象已经包含值,以便创建稍微均匀但不完全均匀的分布,并且我不确定是否使用 Math.random() 为每个插入点选择随机索引采取的最佳方法。
澄清:插入对象的分布应该足够均匀,使得值不会全部集中在一个区域,但也足够不均匀,使得分布不可预测(如果有人去一个接一个地检查这些值,他们将无法通过检测恒定模式来确定下一个值是否是新插入的值)。
最佳答案
不要使用 Math.random。它依赖于 java.util.Random
的全局实例。使用 AtomicLong在引擎盖下。虽然java.util.Random
中使用的PRNG算法是 pretty simple ,性能主要受原子CAS和相关缓存一致性流量的影响。
这对于多线程应用程序来说尤其糟糕(例如 this example ),但即使在单线程情况下也会受到惩罚。
<强> ThreadLocalRandom总是比 Math.random 更可取。它不依赖原子操作,也不会出现争用。它只更新 thread-local state并使用几个 arithmetic and bitwise operations .
这是一个 JMH 基准测试,用于比较 Math.random()
的性能和ThreadLocalRandom.current().nextDouble()
到简单的算术运算。
package bench;
import org.openjdk.jmh.annotations.*;
import java.util.concurrent.ThreadLocalRandom;
@State(Scope.Thread)
public class RandomBench {
double x = 1;
@Benchmark
public double multiply() {
return x * Math.PI;
}
@Benchmark
public double mathRandom() {
return Math.random();
}
@Benchmark
public double threadLocalRandom() {
return ThreadLocalRandom.current().nextDouble();
}
}
结果表明,ThreadLocalRandom 只需几纳秒即可完成工作,其性能可与简单的算术运算相媲美,并且与 Math.random 不同,它可以在多线程环境中完美扩展。
Benchmark Threads Score Error Units
RandomBench.mathRandom 1 34.265 ± 1.709 ns/op
RandomBench.multiply 1 4.531 ± 0.108 ns/op
RandomBench.threadLocalRandom 1 8.322 ± 0.047 ns/op
RandomBench.mathRandom 2 366.589 ± 63.899 ns/op
RandomBench.multiply 2 4.627 ± 0.118 ns/op
RandomBench.threadLocalRandom 2 8.342 ± 0.079 ns/op
RandomBench.mathRandom 4 1328.472 ± 177.216 ns/op
RandomBench.multiply 4 4.592 ± 0.091 ns/op
RandomBench.threadLocalRandom 4 8.474 ± 0.157 ns/op
关于java - Math.random() 运行时间与简单算术运算相比如何?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38546517/