简体   繁体   English

使用ThreadPool查找素数n…n

[英]Finding Prime numbers n…n using a ThreadPool

So as the title suggests I am trying to find all the primes from 0 to MAX_LIMIT 因此,正如标题所示,我正在尝试查找从0到MAX_LIMIT的所有素数

sample input: javac Main.java 8 100 示例输入:javac Main.java 8 100

this means create 8 threads and find primes from 0 to 100, including 100. my program takes two command line arguments: the first is the number of threads, the second is the range of primes (0 to n). 这意味着创建8个线程并找到0到100(包括100)之间的质数。我的程序采用两个命令行参数:第一个是线程数,第二个是质数范围(0到n)。

sample output: 样本输出:

Prime Number: 2 Thread #: 13 质数:2线程#:13

Prime Number: 7 Thread #: 15 质数:7线程#:15

Prime Number: 7 Thread #: 16 质数:7线程#:16

Prime Number: 11 Thread #: 18 质数:11线程#:18

:

Then the system will hang and ill have to stop the process: 然后,系统将挂起,并且必须停止该过程:

Process finished with exit code 137 流程结束,退出代码为137

My question is: 我的问题是:

Why does my thread pool go over its limit (thread numbers like 13 or 16, instead of 1-8) and how can I make the threads not all calculate the same number at the same time? 为什么我的线程池超过了它的限制(线程号为13或16,而不是1-8),又如何使线程不能全部同时计算相同的数字? I'm thinking of using a cache of some sort like adding numbers to an array list or something but I do not know if that would be the correct approach to use. 我正在考虑使用某种高速缓存,例如将数字添加到数组列表之类的东西,但是我不知道这是否是正确的使用方法。

It is possible that I am misunderstanding what a ThreadPool is and am in fact using something completely unrelated to it. 我可能会误解ThreadPool是什么,而实际上却使用了与之完全不相关的东西。

I am also unsure of why it is hanging and not printing all the primes from 0 to 100 in this case. 我也不确定为什么它会挂起并且在这种情况下不能打印从0到100的所有素数。

If there is an easier way to do what I am trying to do I would be interested in hearing it. 如果有一种更简便的方法来做我想做的事,我会对听到它感兴趣。

I'll be here working on this and will check back on this thread frequently. 我将在这里进行研究,并将经常在此线程上进行检查。

Yes this is homework for an operating systems class about threads, I wouldn't normally ask for help but I am at a loss. 是的,这是有关线程的操作系统类的家庭作业,通常我不会寻求帮助,但我很茫然。 All Code is located in one file. 所有代码位于一个文件中。

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);
    }


 }
}

Regarding the second part of your question, take a look at the Sieve of Eratosthenes. 关于问题的第二部分,请看一下Eratosthenes筛。

Change 更改

Runnable worker = new PrimeNumberGen(numToTest); to

Runnable worker = new PrimeNumberGen(i);

You can actually throw away this numToTest variable it's not needed anymore. 实际上,您可以丢弃不再需要的numToTest变量。

Your Thread id is a unique number of a thread. 您的线程ID是线程的唯一编号。 This can start at any number and doesn't have to be sequential. 这可以从任意数量开始,并且不必是连续的。 Over the life of a thread pool you can have more than the maximum number of threads, but no more than the maximum at any time. 在线程池的整个生命周期中,您可以拥有的线程数量超过最大数量,但在任何时候都不能超过最大数量。

BTW If you have to find multiple primes, using a Sieve of Eratosthenes will be much faster as it is a lower time complexity. 顺便说一句,如果您必须找到多个素数,则使用Eratosthenes筛网会更快,因为它的时间复杂度较低。 It is usually single threaded, but it will still be faster. 它通常是单线程的,但仍会更快。

The problem for the duplicate prime numbers is that the threads do not see the updates of the other thread all the time, eg 质数重复的问题在于,这些线程不会一直看到其他线程的更新,例如

Prime Number: 7 Thread #: 15 质数:7线程#:15

Prime Number: 7 Thread #: 16 (Thread 16 does not see the values from thread 15 perhaps they are running on different cores) 质数:7线程号:16(线程16看不到线程15中的值,也许它们在不同的内核上运行)

is because numToTest++; 是因为numToTest ++; is not thread safe since numToTest is not volatile and the operation ++ is not atomic. 不是线程安全的,因为numToTest不是易失性的,并且操作++不是原子的。 I wrote a blog entry under http://blog.vmlens.com/2013/08/18/java-race-conditions-or-how-to-find-an-irreproducable-bug/ to explain this type of bug. 我在http://blog.vmlens.com/2013/08/18/java-race-conditions-or-how-to-find-an-irreproducable-bug/下写了一个博客条目,以解释这种类型的错误。

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

Your program seams to hang since you did not stop the thread pool. 由于没有停止线程池,因此程序将挂起。 See How to stop the execution of Executor ThreadPool in java? 请参阅如何停止Java中的Executor ThreadPool的执行? how to do this. 这个怎么做。

Regarding the thread pool going over its limit, 关于线程池超出其限制,

Change 更改

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

to

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

The thread ID is a positive long number generated when this thread was created, not the actual thread number; 线程ID是创建此线程时生成的正整数,而不是实际的线程号。 calling getName() will outputs something like 调用getName()将输出类似

pool-1-thread-3

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM