使用ThreadPool查找素数n ... n

时间:2013-09-28 03:06:13

标签: java multithreading concurrency primes inner-classes

因为标题暗示我试图找到从0到MAX_LIMIT的所有素数

示例输入:javac Main.java 8 100

这意味着创建8个线程并查找从0到100的素数,包括100。 我的程序有两个命令行参数:第一个是线程数,第二个是素数范围(0到n)。

示例输出:

素数:2线程#:13

素数:7线程#:15

素数:7线程#:16

素数:11线程#:18

然后系统将挂起并且不得不停止该过程:

流程已完成,退出代码为137

我的问题是:

为什么我的线程池超过其限制(线程数字如13或16,而不是1-8) 如何让线程不能同时计算相同的数字? 我正在考虑使用某种类型的缓存,比如将数字添加到数组列表或其他东西 但我不知道这是否是正确的使用方法。

我可能误解了ThreadPool是什么,实际上是在使用与它完全无关的东西。

在这种情况下,我也不确定为什么它会挂起并且不会打印从0到100的所有素数。

如果有更简单的方法来做我想做的事情,我会有兴趣听到它。

我将在此处工作并经常检查这个帖子。

是的,这是关于线程的操作系统类的作业,我通常不会寻求帮助,但我不知所措。所有代码都位于一个文件中。

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class Main {

private static int MAX_THREADS;
private static int MAX_LIMIT;
private static int numToTest = 0;

public static void main(String[] args) {

int max_threads = Integer.parseInt(args[0]);
int max_limit = Integer.parseInt(args[1]);

MAX_THREADS = max_threads;
MAX_LIMIT = max_limit;

Foo();
}



private static void Foo() {

    class PrimeNumberGen implements Runnable {

        int num = numToTest;

        PrimeNumberGen(int n) {num = n;}

        boolean isPrime(int n) { //first test is 0
            if(n<2) return false;
            if(n==2) return true;
            if(n%2==0) return false;

            int max = n/2;
            for(int i=3; i< max; i=i+2) {
                if (n % i == 0)
                    return false;
            }
                    return true;
        }




        public void  run() {
            numToTest++;
            if(isPrime(num)) {

                System.out.println("Prime Number: "+num+" Thread #:
          "+Thread.currentThread().getId());

            }
            else {
                numToTest++;
            }

        }
    }
    //Thread t = new Thread(new PrimeNumberGen(num));
    //t.start();
    ExecutorService executor = Executors.newFixedThreadPool(MAX_THREADS);
    for (int i = 0;i <= MAX_LIMIT; i++) {
        Runnable worker = new PrimeNumberGen(numToTest);
        executor.execute(worker);
    }


 }
}

4 个答案:

答案 0 :(得分:3)

关于问题的第二部分,请看看Eratosthenes的Sieve。

更改

Runnable worker = new PrimeNumberGen(numToTest);

Runnable worker = new PrimeNumberGen(i);

您实际上可以丢弃不再需要的numToTest变量。

答案 1 :(得分:3)

您的线程ID是线程的唯一编号。这可以从任何数字开始,而不必是顺序的。在线程池的生命周期中,您可以拥有超过最大线程数,但不超过最大线程数。

BTW如果你必须找到多个质数,那么使用Eratosthenes筛子将会更快,因为它的时间复杂度更低。它通常是单线程的,但仍然会更快。

答案 2 :(得分:2)

重复素数的问题在于线程不会一直看到其他线程的更新,例如。

素数:7线程#:15

素数:7线程#:16(线程16看不到线程15的值,也许它们在不同的核心上运行)

是因为numToTest ++;因为numToTest不是volatile,而且++不是原子的,所以它不是线程安全的。我在http://blog.vmlens.com/2013/08/18/java-race-conditions-or-how-to-find-an-irreproducable-bug/下写了一篇博客文章来解释这种类型的错误。

一种解决方案是使用AtomicInteger,请参阅http://docs.oracle.com/javase/6/docs/api/java/util/concurrent/atomic/AtomicInteger.html

由于您没有停止线程池,因此您的程序会挂起。请参阅How to stop the execution of Executor ThreadPool in java?如何执行此操作。

答案 3 :(得分:0)

关于线程池超过其限制,

更改

System.out.println("Prime Number: "+num+" Thread #:
      "+Thread.currentThread().getId());

System.out.println("Prime Number: "+num+" Thread #:
      "+Thread.currentThread().getName());

线程ID是创建此线程时生成的正长数,而不是实际的线程数;调用getName()将输出类似

的内容
pool-1-thread-3

参考:https://www.tutorialspoint.com/java/lang/thread_getid.htm