【问题标题】:Find prime numbers in an array using multithreading使用多线程查找数组中的素数
【发布时间】:2016-03-08 22:31:39
【问题描述】:

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

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

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

这是我的代码 - 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);

         }

    }

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

【问题讨论】:

  • 你的意思是什么?您是想以有效的方式在数组中查找素数,还是想学习如何在 java 中创建线程?
  • @SalvadorDali。显然不是第一个。
  • 对不起,我投票结束这个。我理解这个问题的答案,但这是一个关于编写线程安全代码和如何在 Java 中实现共享工作者模式的非常长讲座。你需要在别处找到答案。
  • 简单地根据元素总数和线程数计算一组开始和结束索引。给每个线程分配一个来划分工作。
  • @SalvadorDali 在 Java 中创建线程。但我应该在数百万个数字的数组上使用多线程,然后输出素数。

标签: java arrays multithreading algorithm parallel-processing


【解决方案1】:

问题是每个线程都在循环遍历所有值for (int n = 2; n&lt;=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 相关的部分问题
  • 是的,当我脑死亡时,我认为这比 Eratosthenes 的筛子更容易解释 :) 而且,这似乎是 OP 最不了解的事情。很好地解释了筛子。你应该提到你只需要检查到n BTW 的平方根。
  • 谢谢,疯狂的科学家。我根据您的建议调整了代码。每个线程我仍然有 168 和 168 的输出。会不会是加盟问题?我意识到我的代码存在问题。我不是一个优秀的程序员,我花了几天时间才发现它的缺陷。我希望我至少很接近。我没有做线程的生意,但我必须完成分配给我的任务。
  • 名称修改不谈,您应该在深入学习之前(或至少在学习期间)查看基本的 Oracle 教程:docs.oracle.com/javase/tutorial/essential/concurrency/…。它确实非常好,可能足以满足您的要求。此外,阅读时间应该不会太长。
  • @user3577397 我已经尝试了上面提到的答案,它工作正常。我在 Prime 构造函数中发现只有一个错字。应该是int end
【解决方案2】:

据我了解,您有一个整数数组[a1, a2, ..., an],您想找出其中哪些整数是素数。

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


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

然后再次遍历你的数组,检查你的答案是否在你的素数图中。

P.S.如果你想分解许多数字,类似的想法也成立。


如果您想学习如何在 Java 中处理线程,那么这不是您要寻找的答案。

【讨论】:

  • 在我们之间,我们涵盖了这两个方面。无论哪种方式都需要教程。
【解决方案3】:

我采用了另一种没有线程阻塞的方法。这可能的原因是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
...

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-11-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-04-19
    • 1970-01-01
    • 1970-01-01
    • 2018-08-05
    相关资源
    最近更新 更多