我正在编写一个生成大量随机数的多线程Java程序。
其他详细信息: 这些数字用于创建0-99的随机数列表,不重复,并且列表中存在0-99范围内的每个数字(换句话说,列表包含0-99范围内的100个唯一元素)
生成随机数[事情已经尝试过了!]
ArrayList
中的元素。Collections.shuffle()
。以下是方法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
替换了第二个Collections.shuffle(arr)
循环。
由于生成随机数列表是我算法中最昂贵的部分,我想优化它。这让我想到了问题:
PS:
Collections.shuffle()
比第一种方法慢rngd
从Unix中的硬件生成随机数。有人曾尝试过这个吗?你是怎么做到的?答案 0 :(得分:7)
我认为Collections.shuffle()
的问题是使用默认的Random
实例,它是一个线程安全的单例。你说你的程序是多线程的,所以我可以想象Random
中的同步是一个瓶颈。
如果您喜欢使用Java 7,只需使用ThreadLocalRandom
即可。仔细观察,有shuffle()
版本明确地采用Random
实例:
Collections.shuffle(arr, threadLocalRandom);
其中threadLocalRandom
仅创建一次。
在Java 6上,您只需为每个线程创建一个Random
个实例。请注意,除非每次都能提供随机种子,否则不应每次运行创建Random
的新实例。
答案 1 :(得分:1)
部分问题可能是Integer装箱和拆箱的开销。您可能会发现直接在int[]
重新实现Fisher-Yates shuffle很有帮助。
答案 2 :(得分:0)
我的方法是使用Math.random()
方法生成数字,如示例here中所示,并通过静态init块初始化列表,如下所示:
private static List<int> list = new ArrayList<int>();
static {
for(int i = 0; i < 100; i++) {
// randomize number
list.add(number);
}
}
希望这有帮助,玩得开心!
答案 3 :(得分:0)
调整n个元素的数组a(索引0..n-1):
for i from n − 1 downto 1 do
j ← random integer with 0 ≤ j ≤ i
exchange a[j] and a[i]
检查Fischer and Yattes算法。