Java 与简单算术运算相比,Math.random()运行所需的时间是多少?
在Java中,相对于一个简单的算术运算,Math.random()生成一个数字需要多长时间?我尝试在已经包含值的ArrayList中随机分布对象,这样会创建一个稍微均匀但不完全均匀的分布,并且我不确定是否使用Math.random()为每个插入点选择一个随机索引是最好的方法Java 与简单算术运算相比,Math.random()运行所需的时间是多少?,java,performance,random,Java,Performance,Random,在Java中,相对于一个简单的算术运算,Math.random()生成一个数字需要多长时间?我尝试在已经包含值的ArrayList中随机分布对象,这样会创建一个稍微均匀但不完全均匀的分布,并且我不确定是否使用Math.random()为每个插入点选择一个随机索引是最好的方法 澄清:插入对象的分布应足够均匀,使值不会全部集中在一个区域,但也应足够不均匀,使分布不可预测(如果有人一个接一个地检查这些值,他们将无法通过检测常量模式来确定下一个值是否是新插入的值)。Java文档将此报告为实现,这就是Ma
澄清:插入对象的分布应足够均匀,使值不会全部集中在一个区域,但也应足够不均匀,使分布不可预测(如果有人一个接一个地检查这些值,他们将无法通过检测常量模式来确定下一个值是否是新插入的值)。Java文档将此报告为实现,这就是
Math.random()
最终调用的
public double nextDouble() {
return (((long)next(26) << 27) + next(27))
/ (double)(1L << 53);
}
public double nextDouble(){
返回(((长)下一个(26)(48位))
正如您所看到的,它使用一个简单的算法来生成伪随机值。它只需要一些廉价的操作,因此我不会担心使用它。创建一个随机数是一个简单的操作,您不应该担心它 但是你应该记住几件事
- 最好重用随机实例,每次需要随机值时创建
实例通常是一个错误的决定新的Random()
- 但是,不要同时跨多个线程使用同一个随机实例来避免争用,您可以使用
- 如果你真的这样做了,请改用
java.util.random
的全局实例。虽然java.util.random
中使用的PRNG算法是,但性能主要受原子CA和相关缓存一致性流量的影响
这对于多线程应用程序(如中)来说可能特别糟糕,但即使在单线程情况下也会受到惩罚
总是比Math.random更可取。它不依赖于原子操作,也不受争用的影响。它只更新一个,并使用两个
下面是一个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
Math.random()为您提供了一个随机位置。因此,如果您想要一致的输出(均匀分布),那么“有些”甚至不会每次都发生\您应该创建自己的操作…只需对其进行基准测试!它比一次添加慢得多,但速度足够快,可以多次采样。如果您需要一个以上的随机采样,则可以一次调用所有这些操作(例如,创建随机池).我不知道你在做什么,但我怀疑这里有更多的算法问题。例如:很难实现正确的洗牌。生成随机值(通过Math.random)这是一个相当常见的操作,你也不必担心它,也没有很好的理由。它看起来像是过早的优化。你认为其他的方法是什么?在这种情况下随机是你最好的选择……虽然总是有一个机会,它不是均匀分布的。你可以用一个条件来控制它来重新滚动一个不同的索引。如果它太靠近其他索引,除非你想洗去数以百万计的问题,这不是性能关键。考虑到在鼠标点击的声波从鼠标到点击按钮的人的耳朵的时候,计算机可以创造成千上万(如果不是百万)。关于随机数。不管怎样:我建议根本不要使用
Math.random()
。在大多数情况下,专用的random
实例更通用(也更容易调试)。虽然该算法非常简单,但其性能受性能影响,即使在单线程应用程序中,性能也会受到影响,更不用说在多线程情况下可能存在的争用了。