Java线程Random.nextLong()返回相同的数字

我正在使用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(); } } 

}

您可能不希望每次都创建一个新的Random实例。 而是拥有全球性的。

随机数不是真正随机的,它们是“伪随机的”并且它们需要“种子”值。 如果使用相同的种子,则将生成相同的伪随机值序列。

当您创建Random类的新实例时,您可以自己指定种子,也可以让系统为您选择一个种子。 在Java中,默认种子是当前系统时间(以毫秒为单位),请参阅:

http://download.oracle.com/javase/1.4.2/docs/api/java/util/Random.html#Random%28%29

如果在同一毫秒内创建Random对象,它们将具有相同的值序列。

通常,您希望在所有不同的线程中共享一个Random对象,以避免此类问题。

虽然我没有立即熟悉Random的底层实现,但如果我不得不猜测我会想象调用new Random()委托给new Random(System.currentTimeMillis()) 。 这为在不同时间实例化的Randoms提供了一个相当不同的Random序列。

但是,由于您已经提到异步调用,因此您的调用可能基本上同时执行。 这意味着当线程调用库时,它们同时都在调用new Random()调用,并且Randoms获得相同的种子,因此它们将产生相同的随机序列。

您应该使用SecureRandom,因为您将此用于安全性方面。

我认为Random不是线程安全的,但确实如此。 你应该只得到Random每2 ^ 48个值产生相同的数字。

正如已经指出的那样,Java 1.4和之前的版本有两个Random可以获得相同种子的错误。 我建议你使用Java 6,或者将种子设置为独一无二的。

您还应注意Random使用48位种子。 这意味着它将在2 ^ 48个值之后重复,并且仅产生2 ^ 48个唯一的长值。 如果这对您来说是个问题,请使用更昂贵的SecureRandom,但会产生所有可能的长值。