Java在多线程环境中配置随机数生成器

时间:2015-04-28 05:55:04

标签: java multithreading random

我有一个使用伪随机数的应用程序。当我正在测试应用程序时,我想要重现性,我通过使用随机数生成器的种子来安排。目前,RNG在类中声明,将其用作静态变量:private static Random rng = new Random(seed)。我有几个问题。

  1. 鉴于我想让RNG为可重复性而种子化,声明变量static是否有意义?
  2. 我可能需要添加更多需要随机数的不同类。我应该将RNG移到一个单独的类中,这样我仍然可以在整个应用程序中使用一个种子吗?如果是这样,我应该使用static Random还是单个对象?
  3. 如果我决定在多个线程中使用随机数,会发生什么?似乎如果我使用像2.这样的策略,我可能仍然会失去可预测性,因为我无法确定线程将访问RNG的顺序。 RNG仍将生成相同的,可预测的随机数序列,但是从程序的一次运行到另一次运行,抓取序列中第一个(或第n个)随机数的线程可能不同。
  4. 这对我来说是每个线程都需要自己的RNG,以便在所有运行中重现结果。这是否意味着每个线程都需要自己的种子?如果是这样,那会保证再现性,还是我需要做些什么来消除可能通过多线程引入的随机性?
  5. 有没有办法从单个数字生成种子,最大限度地减少不同RNG之间的相关性?
  6. 换句话说,如果线程0有Random thread0RNG = new Random(seed)而线程1有Random thread1RNG = new Random(seed),我只需要一个种子,但每个线程中的随机数会高度相关。我可以有两个种子,但是我无法将一个程序的运行与一个数字相关联,比如在命令行上传递。说seed0 = someFunction(seed,0)seed1 = someFunction(seed,1)

    是否可行且恰当?

3 个答案:

答案 0 :(得分:2)

是的,您应该为每个线程提供自己的Random对象,以避免由于线程时间而导致无法生成的交错。

你们都可以用相同的数字播种它们,但是它们都将获得完全相同的数字序列。我不知道这是不是一个问题。

如果这是一个问题,你可以有一个“主”随机对象来为其他对象生成种子。每次创建新线程时,都要从主节点获取种子。但是你必须确保每次都以相同的顺序创建所有线程(或者至少检索种子)。

答案 1 :(得分:2)

首先,Random是线程安全的,因此您可以安全地在多个线程中使用它,尽管由于锁定,只有一个Random实例可能会导致性能不佳。为避免这种情况,请改用ThreadLocalRandom

但如果您的情况需要可预测性,那么这不是解决方案。在并发环境中拥有一个共享RNG永远不可预测。因此,你是对的,你需要每个线程一个实例,并且每个实例都必须用种子初始化。

但是如果所有RNG实例都使用相同的种子,那么得到的随机序列不仅会高度相关,而且会相同!因此,您必须为所有RNG使用不同的种子

所以我建议使用中央RNG为所有其他RNG生成种子。但请注意,这只是可预测的,如果RNG的播种顺序是明确定义的 - 在并发环境中这可能不是直接的,但可行。

答案 2 :(得分:0)

为每个线程使用RNG,例如使用ThreadLocalRandom 。如果每个线程都有自己的生成器,多线程不会影响随机性。种子的选择取决于你。