在多个线程之间共享Random
类的一个实例是否有效?并特别从多个线程调用nextInt(int)
?
答案 0 :(得分:62)
它是线程安全的,因为它在多个线程使用时仍然会生成随机数。
Sun / Oracle JVM实现使用synchronized和AtomicLong作为种子来提高跨线程的一致性。但它似乎并未在文档中的所有平台上得到保证。
我不会编写您的程序来要求这样的保证,特别是因为您无法确定将nextInt()
调用的顺序。
答案 1 :(得分:23)
它是线程安全的,虽然并非总是如此。
有关详细信息,请参阅http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6362070。
答案 2 :(得分:8)
根据文档,Math.random()保证多线程使用它是安全的。但是Random类没有。我会假设你必须自己同步。
答案 3 :(得分:7)
是的,Random是线程安全的。 nextInt()
方法调用受保护的next(int)
方法,该方法使用AtomicLong seed, nextseed
(原子长)来生成下一个种子。 AtomicLong
用于生成种子时的线程安全性。
答案 4 :(得分:5)
如上所述,它是线程保存,但根据this article(链接死机)使用java.util.concurrent.ThreadLocalRandom
可能是明智的。 ThreadLocalRandom也是Random的子类,因此它向后兼容。
该文章链接了不同Random的比较分析结果 课程:
java.util.Random
,java.util.concurrent.ThreadLocalRandom
和java.lang.ThreadLocal<java.util.Random>
。结果显示, ThreadLocalRandom的使用效率最高,其次是 ThreadLocal和表现最差的随机本身。
答案 5 :(得分:4)
没有理由多个线程不能全部使用相同的Random。但是,由于该类不是显式线程安全的,并且通过种子维护一系列伪随机数。多个线程最终可能具有相同的随机数。最好为每个线程创建多个Random,并以不同方式为它们播种。
编辑:我刚刚注意到Sun的实现使用了AtomicLong,所以我猜这是线程安全的(Peter Lawrey也注意到了这一点)。
EDIT2 :OpenJDK也使用AtomicLong作为种子。正如其他人所说,虽然依靠这个仍然不好。
答案 6 :(得分:3)
以下是我在不假设Random使用原子变量的情况下处理问题的方法。如果currentTime * thread id
在将来的某个时间相等,它仍然可以随机碰撞,但这对我的需求来说已经很少了。为了真正避免冲突的可能性,您可以让每个请求等待唯一的时钟时间戳。
/**
* Thread-specific random number generators. Each is seeded with the thread
* ID, so the sequence of pseudo-random numbers are unique between threads.
*/
private static ThreadLocal<Random> random = new ThreadLocal<Random>() {
@Override
protected Random initialValue() {
return new Random(
System.currentTimeMillis() *
Thread.currentThread().getId());
}
};
答案 7 :(得分:0)
没有为一个要在多个线程中使用的实例设置Random
类。当然,如果你这样做,你可能会增加无法预测和接近随机数字的可能性。但由于它是一个伪随机生成器,我不明白为什么你需要共享一个实例。是否有更具体的要求?