使用多线程查找数组中的素数

时间:2015-12-04 04:07:04

标签: java arrays multithreading algorithm parallel-processing

我正在尝试修改我工作的顺序主程序并合并多线程。我想指定分割工作的线程数量,然后让每个线程运行一个算法来查找素数,然后显示每个线程中有多少个素数。

问题似乎是每个线程在整个阵列上运行算法,它不会在我指定的所需线程中拆分数组。我尝试了一些其他的东西,但它们只是造成了更多的错误。

截至目前,我正在试验1000个数字的数组。一旦我开始工作,我会在数组中放入数百万个数字,但我只想先做更少的数字。 1000个数组中应该有168个素数。问题是每个线程返回168个素数,这使我相信每个线程都在做同样的事情,而不是分割工作。我的问题是,我怎样才能使用这个程序,让它分割数组并以这种方式运行算法?所以0到499会运行算法并显示带有线程0的素数量,然后500到1000将运行alg并显示该线程中有多少素数。

enter image description here

这是我的代码 - Prime.java

import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

public class Prime extends Thread {


    Scanner scan = new Scanner(System.in);

    static long [] primes = new long [1000];
    static ArrayList<Integer> primeList = new ArrayList<Integer>();


      //int max = num;
   public int count = 0;


   public void run() {
        for (int n = 2; n<=primes.length; n++) {
              boolean prime = true;
                  for (int j = 2; j < n; j++) {
                          if (n%j == 0){
                              prime = false;
                              break;
                                }
                  }

                if (prime){
                        count++;
                        primeList.add(n);

                }

          }
   }
}

Worker.java

 import java.util.ArrayList;
    import java.util.Scanner;

    public class Worker {
        public static void main(String[] args) {
            Scanner scan = new Scanner(System.in);

        System.out.println("How Many threads? ");
        int nThreads = scan.nextInt();  // Create variable 'n'  to handle whatever integer the user specifies.  nextInt() is used for the scanner to expect and Int.

        final Prime[] pThreads = new Prime[nThreads];

        long startTime = System.currentTimeMillis();
        for(int i = 0; i<nThreads; i++){
            pThreads[i] = new Prime();
            pThreads[i].start();

        }
        try {
            for (int i = 0; i < nThreads; i++)
                pThreads[i].join();
        } catch (InterruptedException e) {
            }
            long stopTime = System.currentTimeMillis();

            long elapsedTime = stopTime - startTime;
            System.out.println("Execution time = : "+  elapsedTime);

            System.out.println("----------------------------------------------------");

            int cores = Runtime.getRuntime().availableProcessors();
            System.out.println("How many Cores this Java Program used: " + cores);



          for (int i = 0; i < nThreads; i++)
              System.out.println("Thread " + i + "  Prime count: " + pThreads[i].count); // Display Thread count
         System.out.println("Total prime count: " + Prime.primeList.size()); // Output total amount of primes from the Array List
         for (int i = 0; i < 100; i++) // Display first 100 primes.
            System.out.println(Prime.primeList);

         }

    }

任何帮助将不胜感激。感谢。

3 个答案:

答案 0 :(得分:4)

问题是每个线程都循环遍历所有值for (int n = 2; n<=primes.length; n++)。请注意,primes中的值不使用,只是长度。您可能想尝试为Prime提供一个构造函数,该构造函数包含您要处理的数字范围:

public class Prime extends Thread {

    static ArrayBlockingQueue<Integer> primeList;
    int start, end;

    public Prime(int start, int end) {
        this.start = start;
        this.end = end;
    }

    ...

        for (int n = start; n <= end n++) {

在设置中,将一个段传递给每个线程。另外,不要忘记设置Primes.primeList。请注意,ArrayList 在Java中是安全的,因此将所有线程附加到同一列表是一个非常糟糕的主意。请使用类似java.util.concurrent.ArrayBlockingQueue的内容(请参阅上文)。例如,Worker

Prime.primeList = new ArrayBlockingQueue<>(1000); // Guaranteed to be enough
int step = 1000 / nThreads + 1;
for(int i = 0; i<nThreads; i++){
    pThreads[i] = new Prime(i * step, Math.min(1000, (i + 1) * step - 1));
    pThreads[i].start();
}

所有这些都可以帮助您修补现有的代码,甚至可以使其正常运行。我强烈建议您阅读有关Java线程的实际教程以及查找素数,以便您了解自己的工作做得更好。快速的SO代码修复不会解决代码中的基本金属问题。

答案 1 :(得分:3)

据我所知,你有一个整数数组[a1, a2, ..., an],你想找到哪些整数是素数。

您希望通过为每个线程提供这些整数的一些子集来进行验证来实现此目的。

如果是这种情况,那么你的做法是错误的。只需找到数组中元素的最大值,您就会更快。然后运行Sieve of Eratosthenes以获得低于最大数字的所有素数(请注意,您不需要除以所有整数,最多只能sqrt(n),因为最大素数可以是sqrt(n)

然后再次浏览你的数组并检查你的答案是否在你的素数图中。

P.S。如果你想要分解很多数字,那么类似的想法就成立了。

如果你想学习如何用Java做线程,那么这不是你想要的答案。

答案 2 :(得分:1)

我采用了另一种没有线程阻塞的方法。可能的原因是BigInteger.isProbablePrime() is valid for all 32 bit integers。这是代码:

Prime.java

import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

public class Prime extends Thread {
    public int count = 0;
    public int lowerBound;
    public List<Integer> primeList = new ArrayList<>();

    public void run() {
        for (int n = lowerBound; n <= lowerBound+1000; n++) {
            BigInteger bi = BigInteger.valueOf(n);
            if (bi.isProbablePrime(100)){
                count++;
                primeList.add(n);
            }
        }
    }
}

和Worker.java:

import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

public class Worker {
    public static void main(String[] args) {
         Scanner scan = new Scanner(System.in);
         System.out.println("How Many threads? ");
         int nThreads = scan.nextInt();  // Create variable 'n'  to handle whatever integer the user specifies.  nextInt() is used for the scanner to expect and Int.

         final Prime[] pThreads = new Prime[nThreads];
         long startTime = System.currentTimeMillis();
         for(int i = 0; i<nThreads; i++){
             pThreads[i] = new Prime();
             pThreads[i].lowerBound = 2+1000*i;
             pThreads[i].start();
         }

         try {
             for (int i = 0; i < nThreads; i++)
                 pThreads[i].join();
         } catch (InterruptedException e) {
         }
         long stopTime = System.currentTimeMillis();
         long elapsedTime = stopTime - startTime;
         System.out.println("Execution time = : "+  elapsedTime);
         System.out.println("----------------------------------------------------");
         int cores = Runtime.getRuntime().availableProcessors();
         System.out.println("How many Cores this Java Program used: " + cores);
         for (int i = 0; i < nThreads; i++)
             System.out.println("Thread " + i + "  Prime count: " + pThreads[i].count); // Display Thread count
         List<Integer> allPrimes = new ArrayList<>();
         for (Prime p : pThreads) {
             allPrimes.addAll(p.primeList);
         }
         System.out.println("Total prime count: " + allPrimes.size()); // Output total amount of primes from the Array List
         for (int i = 0; i < 100; i++) // Display first 100 primes.
             System.out.println(allPrimes.get(i));
     }
 }

结果:

How Many threads?
2
Execution time = : 35
How many Cores this Java Program used: 12
Thread 0  Prime count: 168
Thread 1  Prime count: 135
Total prime count: 303
...