lev*_*tov 28 java random java-8
出于某种原因,我常想,java.util.Random是线程安全的,一拉HashMap或BitSet,并且Math.random()被实现为包装访问Random与synchronized块,或ThreadLocalRandom.current().nextDouble().
实际上事实证明它java.util.Random是线程安全的(通过原子).因此需要注意的是:即使我需要在单个线程中使用一些随机输入,使用ThreadLocalRandom也是有意义的,因为内部没有原子读写,编译为锁定指令并发出内存屏障.
而且,由于Java 8 ThreadLocalRandom本质上是一个单例,它的状态保存在某些java.lang.Thread类的字段中.因此,方法ThreadLocalRandom.current()不是访问ThreadLocalMap,而只是静态字段读取,即非常便宜.
我有两个问题:
从计算机科学的角度来看,几个线性同余随机生成器(以ThreadLocalRandoms 的方式初始化)的输出是否与单个线性同余随机生成器(java.util.Random实例)的输出相同"随机" ?
如果回答的第一个问题是肯定的,是否有任何理由写的建设new Random()(不含种子)来代替ThreadLocalRandom.current(),永远不会消失?
更新.我应该调用像ThreadLocalRandom.current().ints().parallel().collect(...)可能是不正确的,因为线程的随机数生成器的状态可能中未初始化ForkJoinPool的工作线程,但看起来,ThreadLocalRandom覆盖方法ints(),longs()以及doubles(),使得上述结构正确.
1...
这取决于实现,但对于 Java 来说,情况不会那么 糟糕,因为 Java 有一个静态的唯一种子原子 long,每次创建 Random 时都会对其进行操作。然而,我不会对其他语言或实现的情况感到惊讶,情况并非如此,它们可能只使用系统时间(Java 也使用系统时间,但组合使用唯一的种子)。也就是说,在某些系统上,您可以为多个线程获得相同的种子。
经过进一步检查和一些实际测试(尽管是脆弱的测试),看来我之前可能是错的,因为同时使用许多(我说的是 100k)随机数生成器实际上更糟糕(即使它们是不同的实例) )。我不完全确定它的种子冲突还是只是实际的全局种子增量变得可预测的事实。当然,这可能只是我的测试工具或方法。
根据维基百科:
随机数生成器,特别是并行计算机的随机数生成器,不应被信任。 [12] 强烈建议检查多个 RNG 的仿真结果,以检查是否引入了偏差。在并行计算机上使用的推荐生成器包括使用序列分裂的组合线性同余生成器和使用独立序列的滞后斐波那契生成器。
所以理论上它应该更好,因为 ThreadLocalRandom 会创建独立的序列,所以也许我的测试有缺陷。
这当然是基于伪随机的。
物理随机性或基于实际熵的安全随机生成器可能会导致差异(即更多/更少的熵),但我不是专家,我无权接触专家。
2...
我无法提出一个特定的用例,但可能是您使用 ExecutorService 不断创建和处置线程(假设它们无法控制这一点),但一次不会有很多线程(即最多 2 个并发线程) 。您可能会发现 ThreadLocalRandom 比创建单个共享 Random 更昂贵。
鉴于您的评论,另一个原因(可能是更好的原因)是您可能希望重置所有进程的种子。如果您有一个使用线程的游戏(不是很多,但让我们假装),您可能需要全局重置种子以进行测试,这比尝试将消息传递到所有正在运行的线程要容易得多,使用对 Random 的 AtomicReference 会更容易。
您可能不想使用 ThreadLocalRandom 的另一个原因是平台原因。某些平台对线程创建以及线程本地创建有特定要求。因此,为了解决“你有一个比随机更大的问题”,请查看Google Apps,其中:
Java 应用程序可以创建新线程,但如何创建有一些限制。这些线程不能“比创建它们的请求更长寿”。(在后端服务器上,应用程序可以生成一个后台线程,该线程可以“比创建它的请求“更长寿”。)
并解决您关于为什么要使用无法重用线程的 ExecutorService 的附加评论:
或者将 com.google.appengine.api.ThreadManager.currentRequestThreadFactory() 返回的工厂对象与 ExecutorService 结合使用(例如,调用 Executors.newCachedThreadPool(factory))。
即不一定重用线程的ThreadPool。
| 归档时间: |
|
| 查看次数: |
3073 次 |
| 最近记录: |