java.util.Random的实例是线程安全。但是,在线程间并发使用相同的java.util.Random实例可能会遇到争用,从而导致性能低下。考虑在多线程设计中使用ThreadLocalRandom。
什么样的争拗,因而表现不佳?有谁能解释一下吗?我不知道随机和ThreadLocalRandom有什么不同的算法。
发布于 2014-04-30 19:03:52
这可能会有一点帮助:
http://thoughtfuljava.blogspot.com/2012/09/prefer-threadlocalrandom-over-random.html
引用自来源:
通常,为了生成随机数,我们要么创建java.util.Random
或Math.random()
的实例,后者在第一次调用时在内部创建java.util.Random
实例。但是,在并发应用程序中,上述使用会导致争用问题。
Random
是用于多个线程的线程安全的。但是,如果多个线程使用相同的Random
__实例,则多个线程共享相同的种子。它导致多个线程之间的争用,从而导致性能下降。
ThreadLocalRandom
是解决上述问题的方法。ThreadLocalRandom
每个线程都有一个Random
实例,并且可以防止争用。
因此,基本上,每个线程使用一个随机实例,就可以停止对所有线程必须使用的种子进行同步。
发布于 2016-09-03 09:54:24
ThreadLocalRandom存在一些问题,无法控制初始种子。我也没有在某个地方找到一种工作的set种子方法。
应该注意的是,当多个线程使用Math.random()时会出现争用,因为它们将在幕后访问类随机类的共享实例,因此使用ThreadLocalRandom还有一种替代方法,这也解决了种子问题。
ThreadLocalRandom使用存储在线程中的种子。他们决定为你做最初的种子,却没有办法控制它。您也可以很好地创建您自己的随机实例,并以线程本地方式使用它。因此,如果您执行以下操作:
/* my thread */
rnd = new Random(my_seed);
/* use rnd */
您也不会看到任何争论。使用相同的种子,您可以得到可复制的随机序列,这可以帮助测试。当您有多个线程时,您可以在这些线程上分发种子。应该有算法在周围产生良好的距离种子。
发布于 2014-04-30 19:14:02
核心算法本质上是相同的。ThreadLocalRandom使用ThreadLocal构造为每个线程创建一个新的随机变量。这保证了来自每个线程的调用不会与每个线程冲突(没有争用)。
看看兰登的这一行,比较一下:
} while (!seed.compareAndSet(oldseed, nextseed));
当您请求下一个值时,兰登接受旧值并生成一个新值。然后,它使用AtomicLong.compareAndSet函数来设置新值,只有在旧值仍然是它使用的值的情况下。如果另一个线程更改了值,则循环将再次运行(直到它是在一个随机数生成中获得和设置值的唯一循环)。因此,可能存在争用,因而可能产生性能影响。
由于保证不发生冲突,ThreadLocalRandom不需要原子函数和线程安全操作/锁定。
有一些权衡,你会想要考虑。使用一个随机数生成器允许一个随机数生成器,如果您想要为您的应用程序使用一个种子,这是非常有用的。如果你只偶尔调用随机,所以冲突很可能是“罕见的”(不是正常情况),那么你可能不会担心冲突,而个人对性能的小影响可能并不重要。如果您在多个线程中每秒钟随机调用数百次,那么您显然希望使用ThreadLocalRandom。
https://stackoverflow.com/questions/23396033
复制相似问题