SplittableRandom有什么用?

11
Java 8增加了一个名为“SplittableRandom”的随机数生成器,似乎是为了与流一起使用。然而,它不清楚它比ThreadLocalRandom更好或更有用。从阅读文档来看,算法被改变以具有更好的统计特性。那么,为什么不称之为BetterThreadLocalRandom并且删除split方法呢?有必要调用split()吗?

更好的ThreadLocalRandom - Jorge Campos
考虑到它不是也不应该成为“ThreadLocalRandom”的即插即用替代品,将其命名为“BetterThreadLocalRandom”之类的名称会误导人。它甚至都不是线程本地的。 - user2357112
我有一个更好的类,我称之为TheBestEverThreadLocalRandom - Scary Wombat
问题更多地在于:为什么需要SplittableRandom,这是一个可以分割随机数的类?对ThreadLocalRandom的批评似乎是关于其实现而不是其API。 - Carl Mastrangelo
2个回答

14
SplittableRandom的实用性在于它是一种确定性随机数生成器。在流处理中,不同的线程可能使用不同的ThreadLocalRandom值,导致每次计算结果不同。Doug Lea在介绍这个类时顺便提到了这一点:

"虽然ThreadLocalRandom选项对许多目的非常有用,但你不会想在高质量的蒙特卡罗模拟中使用它。"

如果模拟有一个有趣的结果,并且它取决于特定的随机数序列,SplittableRandom可以让您重复进行进一步分析。

1
普通的 Random 不能做到这一点吗?我认为 SplittableRandom 的目的是每个实例都可以产生与任何其他实例统计独立的流,而其他实现不能保证。我只是想知道为什么不直接替换 Random 的实现呢... - kaqqao
2
普通随机数可以做到这一点,但它在 next() 函数中支付同步成本,而 SplittableRandom 则不会。 - Carl Mastrangelo

1
你正在比较两个旨在用于不同情境的不同事物。其中一个可以在一定程度上履行另一个的角色。 ThreadLocalRandom 只是本地线程中不同的随机生成器实例,而 SplittableRandom 则是生成器,甚至是生成器的生成器,因为它可以递归地分割并提供新的 SplittableRandom
但是 SplittableRandom 与线程无关,因为它旨在提供能够在功能环境下友好地与流协作的东西。
提供随机数据应该是线程不可知的,即使在流上使用 parallel() 也应该是线程不可知的。我不想在处理流的 lambda 中使用 ThreadLocalRandom.current(),你呢?
此外,使用固定大小的休眠/唤醒线程池来处理并行流的实现将为多个条目使用相同的 ThreadLocalRandom,这在 SplittableRandom 中不会发生,因为它绑定到可能的并行处理路径,而不是特定的线程。

1
当然可以在流中使用ThreadLocalRandom,为什么不能呢?当然不会自己传递实例本身,但是对该调用有什么问题吗? - Carl Mastrangelo
@CarlMastrangelo:因为您甚至不知道哪个线程正在执行用于特定条目的流中的lambda,如果您只有一个线程怎么办?如果您有固定数量的线程怎么办?SplittableRandom提供了无限随机生成机制,这正是我在函数环境中所期望的。 - Jack
为什么线程数量很重要?如果只有一个线程,那么每次调用TLR.current().next()都会返回一个不可预测的数字。SplittableRandom还能提供什么?我希望看到一段代码,在其中使用TLR是不正确的。 - Carl Mastrangelo
这是一种设计哲学问题,你是否曾经使用过OCaml或Haskell等仅支持函数式编程的语言?在函数式环境中,仅仅调用返回静态对象的静态方法来管理随机数据生成并不是一个好的设计思路。这就是为什么SplittableRandom更好,它不是静态的,并且提供了无限数量的随机数据流。 - Jack
TLR 有很多客观的好处,SR似乎没有提供:它是线程安全的,它没有竞争,并且它不分配内存。您提到了随机数流;一个流如何与另一个流不同?它们都是不可预测的数字,这就是TLR提供的。你无法区分由SR生成的数字流和由TLR生成的数字流。似乎没有任何用例可以使用SR生成更好的随机数或更快速。甚至不能简化代码。 - Carl Mastrangelo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接