因为标题暗示我试图找到从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);
}
}
}
答案 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