在Web服务器上,许多线程正在将内容提供给客户端。 A/B测试是在网站上执行的,所以我们需要PRNG为每个会话和测试选择一个变体。 显然,当使用PRNG的单个实例时,它将被同时访问,因此可能需要适当的锁定或其他机制。Java中的并发随机数生成
最初我们使用java.util.Random
(juR),但由于它有缺陷提到例如How good is java.util.Random,我们试着用MersenneTwister代替。 然而,由于Mersenne-Twister relies on an internal state这一事实,我们看到性能大幅下降,所以它需要同步nextInt()
的访问权限。 另一种选择可能是异或移位PRNG,但它与Mersenne Twister具有相同的问题。 你可以找到一个解释,例如这里:http://xorshift.di.unimi.it/
Random
uses a compareAndSet操作,它似乎更快,因为它不需要锁定,但根据类Javadoc它仍然不是线程安全的。相反,建议使用ThreadLocalRandom
,这基本上会导致PRNG池。根据请求,随机可用线程处理HTTPS请求,因此从一组可用的PRNG中选择一个随机PRNG。显然这很快。
从这样的池中产生的随机数与单个PRNG实例中的一样好吗?
另一种方法是使用单个PRNG实例从它预先生成一个值流,例如,通过使用ArrayBlockingQueue
。
哪种解决方案在性能方面效果更好?
对于这个应用程序(选择A或B是否显示给用户),只要它们是均匀分布的,随机数的质量并不重要。 – Henry
您正在预先优化。 Random被记录为线程安全的,并且与Web应用程序所需的所有IO(数据库查询,HTTP请求等)相比,每次启动会话时调用nextBoolean()的性能完全可以忽略不计。 –
这个想法试图在随机数质量方面提出比java.util.Random更好的东西。实际上我们不止有两个变体,所以我们绘制整数。 @Henry据我所读,Random中位数的概率并不是均匀分布的。 – user3001