素数在Java打印中生成线程两次

时间:2018-04-10 17:14:14

标签: java multithreading

我试图在一个点到另一个点之间打印素数,比如说在一个线程中从1到1000,在另一个线程中从1000到2000,但是当我使用foreach循环打印每个线程时,它给出了一个无序的Arraylist,它被打印出来两次。

我正在尝试使用两个并发线程打印1,2,3,5,7 ...请帮助我,以便我能更好地理解线程。

public class PrimeNumberGenerator implements Runnable{

    protected long from, to;
    static ArrayList<Long> primeList = new ArrayList<Long>();

    public  PrimeNumberGenerator(long from,long to)
    {
        this.from = from;
        this.to = to;
    }

    public long count = 0;

    public void run() {
        for(long n=from; n<=to; n++){
            boolean isPrime = true;
            for(long i = 2; i<n; i++) {
                if(n % i==0) {
                    isPrime = false;
                    break;
                }
            }
            if(isPrime) {
                count++;
                primeList.add(n);
            }
        }
    }

    public ArrayList<Long> getPrimes() {
        return primeList;
    }

    public static void main(String[] args) throws Exception {
        // TODO Auto-generated method stub
        PrimeNumberGenerator gen1 = new PrimeNumberGenerator(1L,1000L);
        PrimeNumberGenerator gen2 = new PrimeNumberGenerator(1001L,2000L);
        Thread t1 = new Thread(gen1);
        Thread t2 = new Thread(gen2);
        t1.start();

        t2.start();
        t1.join();
        t2.join();
        gen1.getPrimes().forEach(primeList -> System.out.println(primeList));
        gen2.getPrimes().forEach(primeList -> System.out.println(primeList));
    }
}

2 个答案:

答案 0 :(得分:1)

问题是你有两个线程同时填充相同的ArrayList,因为你的ArrayListstatic(意味着在整个应用程序中只有一个instand共享)

第一个线程可能会添加三个数字,然后第二个线程会添加三个数字,然后再添加第一个数字,从而产生包含

ArrayList
[1, 2, 3, 1009, 1013, 1019, 5, 7, 11]

然后最后你(正确地)等待Thread完成并打印相同的(错误排序的)ArrayList两次!

只需将您的ArrayList设为非静态即可,这样PrimeNumberGenerator ArrayList将拥有自己的var data = {"clave1":"valor1","clave2":"valor2"}; var options = {"data":{}}; $.each(data,function(c,v){ options.data.{c} = v; });

答案 1 :(得分:1)

我建议使用TreeSet来保持素数的有序化。需要正确同步TreeSet以进行多线程访问。

public class PrimeNumberGenerator implements Runnable {

    protected long from, to;
    static Set<Long> primeList = new TreeSet<Long>();

    public PrimeNumberGenerator(long from, long to)
    {
        this.from = from;
        this.to = to;
    }


    public long count=0;

    public void run() {
        for(long n=from;n<=to;n++) {
            boolean isPrime = true;
            for(long i = 2; i<n; i++) {
                if(n % i==0) {
                    isPrime = false;
                    break;
                }
            }
            if(isPrime) {
                count++;
                synchronized(primeList) {
                   primList.add(n);
                }
            }
        }
    }

    public static ArrayList<Long> getPrimes(){
        //Make a copy so we don't need to synchronize outside of this class
        return new ArrayList<>(primeList);
    }

    public static void main(String[] args) throws Exception {
        // TODO Auto-generated method stub
        PrimeNumberGenerator gen1 = new PrimeNumberGenerator(1L,1000L);
        PrimeNumberGenerator gen2 = new PrimeNumberGenerator(1001L,2000L);
        Thread t1 = new Thread(gen1);
        Thread t2 = new Thread(gen2);
        t1.start();

        t2.start();
        t1.join();
        t2.join();
        PrimeNumberGenerator.getPrimes().forEach(primeList -> System.out.println(primeList));

    }
}