从Java 8开始有没有理由写`new Random()`?

出于某种原因,我曾经认为java.util.Random是线程不安全的,a-la HashMapBitSet ,而Math.random()实现为包含对带有synchronized块的RandomThreadLocalRandom.current().nextDouble()

实际上,事实certificatejava.util.Random是线程安全的 (通过atomics)。 因此需要注意:即使我需要在单个线程中进行一些随机输入,使用ThreadLocalRandom也是有意义的,因为内部没有primefaces读写,编译为锁定指令并释放内存障碍。

而且,由于Java 8, ThreadLocalRandom本质上是一个单例,它的状态保存在java.lang.Thread类的某些字段中。 因此,方法ThreadLocalRandom.current()不是对ThreadLocalMap的访问,而只是一个静态字段读取,即非常便宜。

我有两个问题:

  1. 从计算机科学的角度来看,几个线性同余随机生成器(以ThreadLocalRandom s的方式初始化)的输出是否与单个线性同余随机生成器( java.util.Random实例)的输出相同“随机”?

  2. 如果对第一个问题的答案是肯定的,是否有理由编写构造new Random() (没有种子)而不是ThreadLocalRandom.current()

更新。 我认为调用类似ThreadLocalRandom.current().ints().parallel().collect(...)可能不正确,因为Thread的随机生成器状态可能未在ForkJoinPool工作线程中初始化,但看起来ThreadLocalRandom覆盖方法ints()longs()doubles() ,使上述结构正确。

1 …

这取决于实现,但对于Java来说,它将是相同的 而不是坏的,因为Java具有静态唯一种子primefaces长度,每次创建Random时都会对其进行操作 。 但是我不会对其他语言或实现情况感到惊讶,事实并非如此,他们可能只使用系统时间(Java也使用系统时间,但组合使用唯一种子)。 在某些系统上,您可以获得多个线程的相同种子。

经过进一步的检查和一些实际的测试(虽然是脆弱的测试),看起来我可能错了之前 ,实际上更糟糕的是使用很多(我说的是100k)同时的随机数生成器(即使它们是不同的实例) )。 我不完全确定它的种子冲突还是实际全球种子增量变得可预测的事实。 当然,这可能只是我的测试工具或方法。

根据维基百科:

随机数生成器,特别是并行计算机,不应该被信任。[12] 强烈建议使用多个RNG检查模拟结果,以检查是否引入了偏差。 在并行计算机上使用的推荐发生器包括使用序列分裂的组合线性同余生成器和使用独立序列的滞后Fibonacci生成器。

因此理论上它应该更好,因为ThreadLocalRandom会创建独立的序列,所以我的测试可能存在缺陷。

这当然基于伪随机。

物理随机性或基于实际熵的安全随机生成器可能导致差异(即更多/更少的熵),但我不是专家,我无法访问一个。

2 …

我不能提出一个特定的用例,但可能是你使用了一个不断创建和处理线程的ExecutorService(假设它们没有对此的控制)但是从来没有多次(即最多2个并发线程) 。 您可能会发现ThreadLocalRandom更昂贵,而不是创建单个共享Random。

给出评论的另一个原因和可能更好的理由是您可能想要为所有进程重置种子。 如果你有一个使用线程的游戏(不是很多但是让我们假装)你可能想要全局重置种子用于测试目的,使用AtomicReference到Random要比尝试将消息传递给所有正在运行的线程容易得多。

您可能不想使用ThreadLocalRandom的另一个原因是平台原因。 某些平台对线程创建有特定要求,因此对线程局部创建有特定要求。 因此,要解决“ 你有一个更大的问题,而不是randoms ”,请查看Google Apps :

Java应用程序可以创建新线程,但是对于如何执行它有一些限制。 这些线程不能“创建”创建它们的请求“寿命”。 (在后端服务器上,应用程序可以生成后台线程,这个线程可以“创建”创建它的请求“寿命”。)

并解决您为什么要使用无法重用线程的ExecutorService的额外注释:

或者使用com.google.appengine.api.ThreadManager.currentRequestThreadFactory()返回的工厂对象和ExecutorService(例如,调用Executors.newCachedThreadPool(factory))。

即一个不一定重用线程的ThreadPool。