我正在使用OAuth库来调用新的Random()。nextLong()来生成随机数,但是它会在异步调用中生成相同的随机数。我把它缩小到线程化,使Random.nextLong()每隔一段时间返回相同的确切数字。
有谁知道这是否是Java的已知限制?如果是这样,有没有人知道线程安全操作?
编辑:我正在使用Java 1.6
编辑:这是我用来测试我的大型应用程序中发生的事情的一个小程序。我跑了好几次,而且经常会这样,当时间相同的时候会出现相同的随机数。请原谅我的快速编程。public class ThreadedRandom {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
new ThreadedRandom().run();
}
private RandomNumberGenerator _generator;
public ThreadedRandom()
{
_generator = new RandomNumberGenerator();
}
public void run()
{
Runnable r = new Runnable() {
@Override public void run() {
System.out.println(System.currentTimeMillis()+"\t"+_generator.gen());
}
};
Thread t1, t2;
t1 = new Thread(r);
t2 = new Thread(r);
t1.start();
t2.start();
}
private class RandomNumberGenerator {
Random random;
public RandomNumberGenerator()
{
random = new Random();
}
public Long gen() {
return new Random().nextLong();
}
}
}
答案 0 :(得分:4)
您可能不希望每次都创建一个新的Random实例。而是拥有全球性的。
答案 1 :(得分:2)
随机数不是真正随机的,它们是“伪随机的”并且它们需要“种子”值。如果使用相同的种子,将生成相同的伪随机值序列。
当您创建Random类的新实例时,您可以自己指定种子,也可以让系统为您选择一个种子。在Java中,默认种子是当前系统时间(以毫秒为单位),请参阅:
http://download.oracle.com/javase/1.4.2/docs/api/java/util/Random.html#Random%28%29
如果在同一毫秒内创建Random对象,它们将具有相同的值序列。
通常,您希望在所有不同的线程中共享一个Random对象,以避免出现此类问题。
答案 2 :(得分:1)
虽然我不是立即熟悉Random
的基础实现,但如果我不得不猜测我会想象new Random()
委托给new Random(System.currentTimeMillis())
。这为在不同时间实例化的Randoms提供了一个相当不同的Random
序列。
但是,由于您已经提到了异步调用,因此您的调用可能基本上同时执行。这意味着当线程调用库时,它们同时进入new Random()
调用,并且Randoms获得相同的种子,因此它们将产生相同的随机序列。
答案 3 :(得分:1)
您应该使用SecureRandom,因为您将此用于安全性方面。
答案 4 :(得分:0)
我认为Random不是线程安全的,但确实如此。你应该只得到Random每2 ^ 48个值生成相同的数字。
正如已经注意到的,Java 1.4和之前的版本有两个Random可以获得相同种子的错误。我建议您使用Java 6,或者将种子设置为独一无二。
您还应注意Random使用48位种子。这意味着它将在2 ^ 48个值之后重复,并且仅产生2 ^ 48个唯一的长值。如果这对您来说是一个问题,请使用更昂贵的SecureRandom,但会生成所有可能的长值。