首页 > 解决方案 > 使用线程生成唯一随机数(范围)的简单方法?爪哇

问题描述

我想使用 Java 中的线程从给定的输入范围生成唯一随机数列表。例如,给定 1-4 的范围,我会运行 4 个线程,每个线程会生成一个随机数,这样没有两个线程会两次产生相同的值。我想我需要实现一些同步或什么?我试过使用Join(),但它似乎不起作用。

我的构造函数使用输入值来填充具有给定范围的数组列表。在 run 方法中,我生成一个随机值(来自同一范围)并检查它是否在列表中。如果是,我将其从列表中删除并打印该值。这个想法是当另一个线程进来时,它不能再次生成相同的值。

这是我到目前为止所拥有的:

public class Main {

public static void main(String[] args) {
    randomThreadGen randomRange = new randomThreadGen(1, 2);
    Thread thread1 = new Thread(randomRange);
    Thread thread2 = new Thread(randomRange);

    thread1.start();
    try {
        thread1.join();
    } catch (InterruptedException e) {
    }

    thread2.start();
}
}

和这个:

public class randomThreadGen implements Runnable {

private int lowerBound;
private int upperBound;
private final ArrayList<Integer> List = new ArrayList<Integer>();

public randomThreadGen(int lowerb, int upperb) {
    this.lowerBound = lowerb;
    this.upperBound = upperb;
    for (int i = lowerb; i < upperb + 1; i++) { // populate list with values based on lower and upperbounds specified from main
        List.add(i);
    }

}

@Override
public void run() {
    // generate random value
    // check if in list. If in list, remove it
    // print value
    // otherwise try again
    int val = ThreadLocalRandom.current().nextInt(lowerBound, upperBound+1); // generate random value based on lower and upper bound inputs from main
    
    while(true){
        if(List.contains(val)){
            List.remove(new Integer(val));
            System.out.println("Random value for " + Thread.currentThread().getName() + "  " + val);
            System.out.println("List values:  " + List);
        }
        break;
        
    }
    
    }
}'''

这个低范围的测试用例是为了使测试变得容易。有时它会起作用,Thread0 会生成与 Thread01 不同的值(例如 1 和 2 或 2 和 1)。但有时它不会(似乎它们生成相同的值,在这种情况下我的代码只打印一个值)例如,“Thread02 1”,仅此而已。

有任何想法吗?除了 有没有其他方法可以做到这一点join()

标签: javamultithreadingthread-safetyjava-threadsthread-synchronization

解决方案


这是一个很容易的任务。只需使用并发哈希图来防止重复。确保将边界 int 和 hashmap 声明为 final。需要 Thread.join 以保证在所有线程完成工作后打印结果。还有其他有效的技术可以代替 join,但它们不适合新手。

尝试这个:

import java.util.concurrent.ThreadLocalRandom;
import java.util.*;
import java.util.concurrent.*;


public class Main {
    final static int low = 0;
    final static int up = 5;
    final static Set < Integer > inthashmap = ConcurrentHashMap.newKeySet();
    
    // threadhashmap is needed to track down all threads generating ints
    final static Set < Thread > threadhashmap = ConcurrentHashMap.newKeySet();

    public static void main(String[] args) throws InterruptedException {
        for (int i = 0; i < up - low + 1; i++) {
            Thread t = new Thread() {
                public void run() {
                    int randomNum;
                    try {
                        randomNum = ThreadLocalRandom.current().nextInt(low, up + 1);
                        inthashmap.add(randomNum);
                        System.out.println("A new random int generated : " + randomNum);
                    } finally {

                    }
                }
            };
            threadhashmap.add(t);
            t.start();
        }
        
        //by iterating through all threads in threadhashmap
        // and joining them we guarantee that all threads were completed
        // before we print the results of work of those threads (i.e. ints)
        Iterator<Thread> iterator = threadhashmap.iterator();

        while (iterator.hasNext())
            iterator.next().join();

        System.out.println("Unique ints from hashmap:");
        inthashmap.forEach(System.out::println);
    }
}

输出:

A new random int generated : 2
A new random int generated : 3
A new random int generated : 3
A new random int generated : 0
A new random int generated : 0
A new random int generated : 2
Unique ints from hashmap:
0
2
3

推荐阅读