我有一个使用伪随机数的应用程序。当我正在测试应用程序时,我想要重现性,我通过使用随机数生成器的种子来安排。目前,RNG在类中声明,将其用作静态变量:private static Random rng = new Random(seed)
。我有几个问题。
static
是否有意义?static Random
还是单个对象?换句话说,如果线程0有Random thread0RNG = new Random(seed)
而线程1有Random thread1RNG = new Random(seed)
,我只需要一个种子,但每个线程中的随机数会高度相关。我可以有两个种子,但是我无法将一个程序的运行与一个数字相关联,比如在命令行上传递。说seed0 = someFunction(seed,0)
和seed1 = someFunction(seed,1)
答案 0 :(得分:2)
是的,您应该为每个线程提供自己的Random对象,以避免由于线程时间而导致无法生成的交错。
你们都可以用相同的数字播种它们,但是它们都将获得完全相同的数字序列。我不知道这是不是一个问题。
如果这是一个问题,你可以有一个“主”随机对象来为其他对象生成种子。每次创建新线程时,都要从主节点获取种子。但是你必须确保每次都以相同的顺序创建所有线程(或者至少检索种子)。
答案 1 :(得分:2)
首先,Random
是线程安全的,因此您可以安全地在多个线程中使用它,尽管由于锁定,只有一个Random
实例可能会导致性能不佳。为避免这种情况,请改用ThreadLocalRandom
。
但如果您的情况需要可预测性,那么这不是解决方案。在并发环境中拥有一个共享RNG永远不可预测。因此,你是对的,你需要每个线程一个实例,并且每个实例都必须用种子初始化。
但是如果所有RNG实例都使用相同的种子,那么得到的随机序列不仅会高度相关,而且会相同!因此,您必须为所有RNG使用不同的种子
所以我建议使用中央RNG为所有其他RNG生成种子。但请注意,这只是可预测的,如果RNG的播种顺序是明确定义的 - 在并发环境中这可能不是直接的,但可行。
答案 2 :(得分:0)
为每个线程使用RNG,例如使用ThreadLocalRandom 。如果每个线程都有自己的生成器,多线程不会影响随机性。种子的选择取决于你。