简体   繁体   English

在Java中生成随机数的快速高效方法

[英]Quick and Efficient way to generate random numbers in Java

I am writing a multi-threaded Java program that generates lot of random numbers. 我正在编写一个生成大量随机数的多线程Java程序。

Additional Details: These numbers are used to create a list of random numbers from 0-99 without repetition and such that every number in the range 0-99 exists in the list (In other words, the list contains 100 unique elements in the range 0-99). 其他详细信息:这些数字用于创建0-99的随机数列表,不重复,并且列表中存在0-99范围内的每个数字(换句话说,列表包含0范围内的100个唯一元素-99)。

Generating Random Numbers [Things already tried!] 生成随机数[事情已经尝试过!]

  1. I have an ArrayList of numbers from 0-100. 我有一个0-100的数字列表。 I generate a random number and use it as an index which is used to pop out an element from the ArrayList . 我生成一个随机数并将其用作索引,用于从ArrayList弹出一个元素。
  2. I have used Collections.shuffle() . 我使用了Collections.shuffle()

Here is the code for approach 1: 以下是方法1的代码:

ArrayList<Integer> arr = new ArrayList<Integer>(); 
for (int i = 0; i < N; i++){
 arr.add(i, i);
}

for(int i=0; i<N; i++){
  int indx = rand.nextInt(arr.size());
  res.add(arr.get(indx));
  arr.remove(indx);
}

For second approach, I replaced the second for loop with Collections.shuffle(arr) . 对于第二种方法,我用Collections.shuffle(arr)替换了第二个for循环。

As generating list of random numbers is the most expensive part of my algorithm, I want to optimize it. 由于生成随机数列表是我算法中最昂贵的部分,我想优化它。 This brings me to the questions: 这让我想到了一些问题:

  1. What is the fastest way to generate random numbers? 生成随机数的最快方法是什么?
  2. What is the fastest way to generate the list of random numbers as described above? 如上所述,生成随机数列表的最快方法是什么?

PS: PS:

  1. I found Collections.shuffle() to be slower than the first approach 我发现Collections.shuffle()比第一种方法慢
  2. Someone suggested me using rngd to generate random numbers from hardware in Unix. 有人建议我使用rngd从Unix中的硬件生成随机数。 Has anyone tried this before? 有人曾尝试过这个吗? How do you do that? 你是怎样做的?

I think the problem with Collections.shuffle() is that is uses default Random instance which is a thread-safe singleton. 我认为Collections.shuffle()的问题是使用默认的Random实例,它是一个线程安全的单例。 You say that your program is multi-threaded, so I can imagine synchronization in Random being a bottle-neck. 你说你的程序是多线程的,所以我可以想象Random中的同步是一个瓶颈。

If you are happily running on Java 7, simply use ThreadLocalRandom . 如果您在Java 7上运行愉快,只需使用ThreadLocalRandom Look carefully, there is a version of shuffle() taking Random instance explicitly: 仔细看,有一个版本的shuffle()明确地采用Random实例:

Collections.shuffle(arr, threadLocalRandom);

where threadLocalRandom is created only once. 其中threadLocalRandom只创建一次。

On Java 6 you can simply create a single instance of Random once per thread. 在Java 6上,您可以简单地为每个线程创建一个Random实例。 Note that you shouldn't create a new instance of Random per run, unless you can provide random seed every time. 请注意,除非每次都可以提供随机种子,否则不应每次运行创建一个新的Random实例。

Part of the problem might be the overhead of the Integer boxing and unboxing. 部分问题可能是Integer装箱和拆箱的开销。 You might find it helpful to reimplement the Fisher-Yates shuffle directly on an int[] . 您可能会发现直接在int[]上重新实现Fisher-Yates shuffle很有帮助。

My approach woul be to generate the numbers with the Math.random() method as in the example here and initialize the list via a static init block like this: 我的方法是使用Math.random()方法生成数字,如此处的示例并通过静态init块初始化列表,如下所示:

private static List<int> list = new ArrayList<int>();
static {
  for(int i = 0; i < 100; i++) {
    // randomize number
    list.add(number);
  }
}

Hope this helped, have Fun! 希望这有帮助,玩得开心!

To shuffle an array a of n elements (indices 0..n-1): 要改组n个元素的数组(索引0..n-1):

for i from n − 1 downto 1 do
       j ← random integer with 0 ≤ j ≤ i
       exchange a[j] and a[i]

Check Fischer and Yattes algorithm. 检查Fischer和Yattes算法。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM