首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >特定时间戳的唯一随机数

特定时间戳的唯一随机数
EN

Stack Overflow用户
提问于 2013-10-01 08:50:33
回答 3查看 9.6K关注 0票数 3

我是一种在java中学习随机数生成和多线程的概念。

其想法是不要在特定毫秒内产生重复的随机数1000范围(考虑到,不超过50个数据,以多线程的方式将在毫秒内处理)。因此,在特定时间生成的随机数列表是唯一的。你能给我任何的想法吗,因为我在特定的毫秒内产生了几个重复的随机数(也有相当大的概率)。

我试过以下失败的地方。

代码语言:javascript
复制
Random random = new Random(System.nanoTime());
double randomNum = random.nextInt(999);

//

代码语言:javascript
复制
int min=1; int max=999;
double randomId = (int)Math.abs(math.Random()* (max - min + 1) + min);

//

代码语言:javascript
复制
Random random = new Random(System.nanoTime()); // also tried new Random();
double randomId = (int)Math.abs(random.nextDouble()* (max - min + 1) + min);

当我附加正在生成的时间戳时,在多线程环境中,我看到为5000+唯一数据生成的is (大约8-10次)相同(2-4次)。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2013-10-01 09:04:56

这个类将允许您从某个范围获得非重复值,直到整个范围被使用为止。一旦使用了范围,它将被重新初始化。

类附带了一个简单的测试。

如果希望使类线程安全,只需将synchronized添加到nextInt()声明即可。

然后,您可以使用单例模式或仅使用一个静态变量从多个线程访问生成器。这样,所有线程都将使用相同的对象和相同的唯一id池。

代码语言:javascript
复制
public class NotRepeatingRandom {
    int size;
    int index;
    List<Integer> vals;
    Random gen = new Random();

    public NotRepeatingRandom(int rangeMax) {
      size = rangeMax;
      index = rangeMax; // to force initial shuffle
      vals = new ArrayList<Integer>(size);
      fillBaseList();
    }

    private void fillBaseList() {
      for (int a=0; a<size; a++) {
        vals.add(a);
      }
    }

    public int nextInt() {
      if (index == vals.size()) {
          Collections.shuffle(vals);
          index = 0;
      }
      int val = vals.get(index);
      index++;      
      return val;
    }

    public static void main(String[] args) {
        NotRepeatingRandom gen = new NotRepeatingRandom(10);
        for (int a=0; a<30; a++) {
            System.out.println(gen.nextInt());
        }
    }
}
票数 2
EN

Stack Overflow用户

发布于 2013-10-01 09:11:17

首先,您应该使用new Random(),因为它看起来像像这样 (细节取决于Java ):

代码语言:javascript
复制
 public Random() { this(++seedUniquifier + System.nanoTime()); }
 private static volatile long seedUniquifier = 8682522807148012L;

也就是说,它已经使用了nanoTime(),并确保具有相同nanoTime()结果的不同线程获得不同的种子,而new Random(System.nanoTime())没有。

(编辑: Pyranja指出这是Java6中的一个bug,但它是固定的在Java 7中

代码语言:javascript
复制
public Random() {
    this(seedUniquifier() ^ System.nanoTime());
}

private static long seedUniquifier() {
    // L'Ecuyer, "Tables of Linear Congruential Generators of
    // Different Sizes and Good Lattice Structure", 1999
    for (;;) {
        long current = seedUniquifier.get();
        long next = current * 181783497276652981L;
        if (seedUniquifier.compareAndSet(current, next))
            return next;
    }
}

private static final AtomicLong seedUniquifier
    = new AtomicLong(8682522807148012L);

)

第二,如果从1到1000生成50个随机数,那么由于生日悖论的存在,一些数字是相同的概率是相当高的。

第三,如果您只想要唯一的ids,可以使用AtomicInteger计数器而不是随机数。或者,如果您想要一个随机的部分开始,也附加一个计数器以及确保唯一性。

票数 4
EN

Stack Overflow用户

发布于 2013-10-01 09:16:12

如果我正确理解你的问题,多个线程同时创建自己的随机类实例,而所有线程都生成相同的随机数?生成相同的数目,因为所有在同一时间创建的随机实例,即具有相同种子的随机实例。

要解决这个问题,只需创建一个由所有线程共享的随机类实例,以便所有线程在同一个实例上调用nextDouble()。Random.nextDouble()类是线程安全的,它将使用每次调用隐式更新其种子。

代码语言:javascript
复制
//create only one Random instance, seed is based on current time
public static final Random generator= new Random();

现在所有线程都应该使用相同的实例:

代码语言:javascript
复制
double random=generator.nextDouble() 
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/19111827

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档