【问题标题】:how random is Math.random() in java across different jvms or different machinesjava中的Math.random()在不同jvm或不同机器上的随机性如何
【发布时间】:2012-04-01 10:44:39
【问题描述】:

我有一个跨许多不同物理服务器的大型分布式程序,每个程序产生许多线程,每个线程在其操作中使用Math.random() 从许多公共资源池中提取一块。

目标是在所有操作中平均利用池。有时,通过查看资源池上的快照来查看它在那个瞬间获得了哪些片段,它看起来并不那么随机(实际上可能是这样,但很难衡量和确定)。

有没有比Math.random() 更好并且表现同样出色(至少不会差很多)的东西?

【问题讨论】:

  • +1 提出一个好问题。如果您找到答案,请告诉我:)
  • 为什么不对公共资源池使用一些调度器?
  • @vitalik:资源池前的任何类型的控制器/调度程序都需要协调和降级性能,在这种情况下会带来灾难性的并发症。
  • @user unknown:他正在使用 Math.random(),所以这是他绝对没有犯的一个错误。

标签: java random


【解决方案1】:

Math.random() 基于java.util.Random,后者基于linear congruential generator。这意味着它的随机性并不完美,但对于大多数任务来说已经足够了,而且听起来它应该足以完成你的任务。

但是,听起来您正在使用Math.random()double 返回值在固定数量的选项之间进行选择,这可能会进一步降低随机性的质量。使用java.util.Random.nextInt() 会更好——只要确保重复使用相同的Random 对象即可。

有时,通过查看资源池上的快照来查看它在那个瞬间获得了哪些片段,它看起来并不那么随机

我们的大脑非常善于发现完全随机的模式,所以这几乎没有任何意义。

【讨论】:

  • 关于 Random.nextInt() 的好点,目前我只是将随机双精度数乘以 n,然后将其四舍五入到最接近的整数,这与 Random().nextInt() 有很大不同吗?跨度>
  • @user881480: 是的 - Random 产生整数,Math.random() 做额外的工作将其转换为双精度,只是为了将其转换回整数。这种双重转换可能会降低随机性的质量(不确定,但可能会)。
【解决方案2】:

Math.Random 的算法对于任何平台都“足够随机”。用于创建伪随机数的数学模型是一个很好的模型。这取决于您使用的线程数。除了非常多的线程之外,这不会给你均匀分布(随机数的性质),然后 Math.random() 会给你很多开销。

尝试一个更好的选择:创建一个资源池类,它可以均匀地分配它们 - 然后只在“分布”方法中保护它的关键部分。

【讨论】:

  • 为什么随机数不能给你一个均匀分布?在我的例子中,每个程序的线程数是几百个,但是每个线程执行许多操作(每秒 1 个,每个操作调用 Math.random())。
  • 资源池类如何随机分配资源?它必须使用 Math.random() 吗?
  • 你不需要随机分发,只需要创建一个简单的类Resources,一个同步的nextResource()方法。这样你就可以一个一个地浏览它们,确保分布均匀。此外,除了少数非常特殊的情况外,使用数百个线程会产生比节省时间更多的开销;您应该将线程数量限制在系统可以有效使用的范围内。
【解决方案3】:

这个帖子很有用: How good is java.util.Random?

另一种选择:

  • 在初始化随机实例时生成随机种子
  • 如果你使用 linux 使用 /dev/urandom

【讨论】:

  • 我不想从 Java 调用外部进程,因为它会降低性能,我以每秒 1 次操作的速度运行,并且每天有很多(数十万或百万)服务器。
  • 所以我能做的最简单的事情就是创建你自己的更长周期的生成器(如链接中所述)。您还必须记住,获得 1,1,1,1,1 的机会与 45,1002,783,199,6 的机会相同
【解决方案4】:

根据 javadoc Math.random() 只是使用 java.util.Random 的一种简单方法。也就是说,这只是一个伪随机算法。检查算法的随机性的一种简单方法是在 x/y 网格上绘制随机点。您应该找不到任何模式。

要获得真正的随机数,您可以使用 http://www.random.org 之类的服务。如果这很慢,也许定期调用它来播种 java.util.Random 可以让你更接近真正的随机。

【讨论】:

  • new java.util.Random() 如何获得可能不同的种子?
猜你喜欢
  • 1970-01-01
  • 2016-04-21
  • 1970-01-01
  • 1970-01-01
  • 2011-01-21
  • 2019-04-15
  • 1970-01-01
  • 1970-01-01
  • 2010-12-30
相关资源
最近更新 更多