【发布时间】:2019-11-11 16:02:48
【问题描述】:
我是java新手,我正在尝试编写一个带有两个参数的程序:
- 我们必须将素数相加的数字
- 我们必须执行此操作的线程数
所以我使用了一个名为 Eratosthene 的方法,它存储了一个 boolean 数组,如果一个数字是素数,我们将其标记为真,然后我们标记所有的倍数这个数字是假的。
我尝试将我的数组划分为每个线程的子数组,并在每个子数组中进行操作,最后将子数组的所有结果相加。
但我不知道我在哪里做错了:有时程序并没有给出好的结果。
这是我的代码:
SumPrime.java
import java.util.*;
import java.util.concurrent.*;
public class SumPrimes {
private boolean array[];
private int numberOfWorkers;
private Semaphore allFinished;
public SumPrimes(int num, int threads){
array = new boolean[num];
numberOfWorkers = threads;
for (int i = 2; i < num; i++)
array[i] = true;
}
private class SumParallel extends Thread {
int min;
int max;
long sum;
SumParallel(int min, int max){
this.min = min;
this.max = max;
sum = 0;
}
public void run() {
for (int i = min; i < max; i++) {
if (array[i]) {
for (int j = min; j*i < array.length; j++) {
array[i*j] = false;
}
sum += i;
}
}
allFinished.release();
}
public long getSum() {
return sum;
}
}
public void SumInParallel() {
allFinished = new Semaphore(0);
List<SumParallel> workers = new ArrayList<SumParallel>();
int lengthOfOneWorker = array.length / numberOfWorkers;
for (int i = 0; i < numberOfWorkers; i++) {
int start = i * lengthOfOneWorker;
int end = (i+1) * lengthOfOneWorker;
if (i == numberOfWorkers - 1)
end = array.length;
SumParallel worker = new SumParallel(start, end);
workers.add(worker);
worker.start();
}
try {
allFinished.acquire(numberOfWorkers);
} catch (InterruptedException ignored) {}
int sum = 0;
for (SumParallel w : workers){
sum += w.getSum();
}
System.out.println("The sum of prime numbers is: " + sum);
}
public static void main(String[] args) {
int limitNum = Integer.parseInt(args[0]);
int threadNum = Integer.parseInt(args[1]);
SumPrimes sum_primes = new SumPrimes(limitNum, threadNum);
sum_primes.SumInParallel();
}
}
你可以这样运行程序:
java SumPrimes 1000 3
我愿意接受任何改进我的代码的建议。
【问题讨论】:
-
无关:您应该使用
CountDownLatch,而不是Semaphore。参见例如CountDownLatch vs. Semaphore. -
如果您提供一个产生错误值的运行示例以及实际值应该是什么,这将有所帮助。
-
@JosephLarson 例如,如果我这样做
java SumPrimes 200 4真正的答案是4227并且如果我使用此命令多次运行我的程序,有时我会得到很好的答案,但有时我会得到答案要么离好结果太远,要么离好结果太近 -
这就是所谓的竞争条件,这就是为什么多线程编程会很困难,因为当你做错时结果会有所不同,而且它可能恰好看起来是正确的的时间,所以你甚至可能不知道(一开始)。为什么这里有比赛条件?因为第一个线程更新了其他线程使用的数组值。
-
@Andreas 我把你发送的链接加红了,但我看不出有理由不使用
Semaphore。你能解释一下为什么我应该使用CountDownLatch吗?
标签: java multithreading sum primes