【发布时间】:2015-06-06 12:50:29
【问题描述】:
我目前正在开发我的第一个多线程软件 - 一个计算素数的程序......
基本上我创建了 n(线程数)可运行对象。这些runnables 被添加到一个ArrayList。他们检查一个数字是否是素数。如果数字是素数,我将其添加到一个长数组中以备后用。因为我希望素数在这个数组中的顺序正确,所以我需要特定的线程来等待其他线程。我通过循环遍历 ArrayList(见上文)并等待检查较低数字的线程来做到这一点。
线程完成后,我想将其从给定的 ArrayList 中删除,但我不能,因为其他线程仍在循环通过它(我猜这就是 ConcurrentModificationException 发生的原因 - 这是我第一次使用线程...... )。
我真诚地希望你们中的任何人都可以帮助我:)
非常感谢您!
马蒂亚斯
我的可运行类(我只是在main方法中创建了这个类的四个对象):
导入 java.util.ArrayList;
public class PrimeRunnable implements Runnable {
//Static Util
public static ArrayList<PrimeRunnable> runningThreads = new ArrayList<PrimeRunnable>();
public static long[] primes;
public static int nextFreeIndex = 1;
public static long nextPossiblePrime = 3;
//Object specific
private long numberToCheck;
private Thread primeThread;
private String threadName;
private long threadID;
public PrimeRunnable() {
numberToCheck = nextPossiblePrime;
increaseNextPossiblePrime();
threadName = "ThreadToCheck" + numberToCheck;
threadID = numberToCheck;
runningThreads.add(this);
}
@Override
public void run() {
boolean isPrime = true;
double sqrtOfPossiblePrime = Math.sqrt(numberToCheck);
long lastDevider = 0;
for(int index = 0; index < nextFreeIndex; index++) {
lastDevider = primes[index];
if(numberToCheck%primes[index] == 0) {
isPrime = false;
break;
}
if(primes[index] > sqrtOfPossiblePrime) {
break;
}
}
while(lastDevider < sqrtOfPossiblePrime) {
lastDevider += 1;
if(numberToCheck%lastDevider == 0) {
isPrime = false;
break;
}
}
if(isPrime) {
//Wait for lower Threads.
for(PrimeRunnable runnable : runningThreads) {
if(runnable.getThreadID() < this.getThreadID()) {
try {
runnable.primeThread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
primes[nextFreeIndex] = numberToCheck;
increaseNextFreeIndex();
System.out.println(numberToCheck);
}
runningThreads.remove(this);
}
public void start() {
if(primeThread == null) {
primeThread = new Thread(this, threadName);
}
primeThread.start();
}
public void reset() {
numberToCheck = nextPossiblePrime;
increaseNextPossiblePrime();
threadName = "ThreadToCheck" + numberToCheck;
threadID = numberToCheck;
//No need to readd into runningThread, since we only manipulate an already existing object.
primeThread = new Thread(this, threadName);
primeThread.start();
}
public static void setUpperBorder(int upperBorder) {
if(primes == null) {
primes = new long[upperBorder];
primes[0] = 2;
} else {
System.err.println("You are not allowed to set the upper border while running.");
}
}
public long getNumberToCheck() {
return numberToCheck;
}
private void increaseNextPossiblePrime() {
nextPossiblePrime += 2;
}
private void increaseNextFreeIndex() {
nextFreeIndex += 2;
}
public long getThreadID() {
return threadID;
}
public boolean isAlive() {
return primeThread.isAlive();
}
}
【问题讨论】:
-
请发布堆栈跟踪。
-
尝试使用像 Vector 这样的线程安全集合或同步 ArrayList
runningThreads 和 long[] primes。 -
您的
start()方法看起来有些可疑。您知道Thread只能启动一次吗?您的PrimeRunnable.start()方法看起来像是要多次调用它。 -
强制任务按照它们开始的顺序完成似乎是个坏主意。您将失去很多并发处理的机会,因为您通常会有一个线程正在处理一个难题(即,一个真正为素数的数字),而没有其他已经完成任务的线程处于空闲状态,等待轮到他们返回结果。你说你需要保持结果排序。您是否考虑过将结果存储到一个容器中,以便在添加每个新成员时保持其内容排序(例如,
java.util.SortedSet)?
标签: java multithreading exception arraylist concurrentmodification