带有ConcurrentModificationException的Java线程
带有ConcurrentModificationException的Java线程,java,multithreading,exception,arraylist,concurrentmodification,Java,Multithreading,Exception,Arraylist,Concurrentmodification,我目前正在开发我的第一个多线程软件-一个计算素数的程序。。。 基本上,我创建了n个(线程数)可运行文件。这些可运行项被添加到ArrayList中。他们检查一个数字是否是素数。如果这个数字是素数,我将它添加到一个长数组中供以后使用。因为我希望素数在这个数组中的顺序正确,所以我需要特定的线程来等待其他线程。我通过在ArrayList中循环(见上文)并等待线程来完成这项工作,线程会检查一个较小的数字 在一个线程完成后,我想将其从给定的ArrayList中删除,但我不能,因为其他线程仍在循环通过它(我想
我目前正在开发我的第一个多线程软件-一个计算素数的程序。。。
基本上,我创建了n个(线程数)可运行文件。这些可运行项被添加到ArrayList中。他们检查一个数字是否是素数。如果这个数字是素数,我将它添加到一个长数组中供以后使用。因为我希望素数在这个数组中的顺序正确,所以我需要特定的线程来等待其他线程。我通过在ArrayList中循环(见上文)并等待线程来完成这项工作,线程会检查一个较小的数字
在一个线程完成后,我想将其从给定的ArrayList中删除,但我不能,因为其他线程仍在循环通过它(我想这就是ConcurrentModificationException发生的原因-这是我第一次使用线程…)
我真诚地希望你们中的任何人都能帮助我:)
非常感谢你!
马蒂亚斯 我的runnable类(我只在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();
}
}
公共类PrimeRunnable实现Runnable{
//静态Util
public static ArrayList runningThreads=new ArrayList();
公共静态长[]素数;
公共静态int-nextFreeIndex=1;
公共静态长nextPossiblePrime=3;
//特定对象
私人长途电话检查;
私有线程;
私有字符串threadName;
私人长线;
公共素数可运行(){
numberToCheck=nextPossiblePrime;
增加nextPossiblePrime();
threadName=“ThreadToCheck”+numberToCheck;
threadID=编号检查;
runningThreads.add(这个);
}
@凌驾
公开募捐{
布尔值isPrime=true;
double sqrtOfPossiblePrime=Math.sqrt(numberToCheck);
长lastDevider=0;
对于(int index=0;indexsqrtOfPossiblePrime){
打破
}
}
while(lastDevider
一个PrimeListener
类如何,它包含一个同步方法publishPrime
,将prime插入列表中的正确位置?如果从链接列表的最后一个索引开始,则在列表的正确位置插入不会花费太多时间
或者,您也可以将其插入SortedSet
(实现:TreeSet
)。我想你根本不想要任何重复的素数。在这种情况下,可以直接使用,而不是侦听器
请注意,您似乎仍然停留在较低级别的结构上。在Java上并发编程时,使用更高级别的构造(执行器、未来、并发队列等)是值得的 如果一个PrimeListener
类包含一个同步方法publishPrime
,该方法在列表中的正确位置插入prime,那么该类会怎么样?如果从链接列表的最后一个索引开始,则在列表的正确位置插入不会花费太多时间
或者,您也可以将其插入SortedSet
(实现:TreeSet
)。我想你根本不想要任何重复的素数。在这种情况下,可以直接使用,而不是侦听器
请注意,您似乎仍然停留在较低级别的结构上。在Java上并发编程时,使用更高级别的构造(执行器、未来、并发队列等)是值得的
fail fast和fail safe迭代器之间的主要区别是
收集时是否可以对其进行修改
迭代。故障安全迭代器允许这一点;快速失败迭代器不需要
快速失效迭代器直接在
public class PrimeRunnableMain {
public static void main(String[] args) {
PrimeRunnable.setUpperBorder(10);
PrimeRunnable primeRunnable1 = new PrimeRunnable();
PrimeRunnable primeRunnable2 = new PrimeRunnable();
PrimeRunnable primeRunnable3 = new PrimeRunnable();
PrimeRunnable primeRunnable4 = new PrimeRunnable();
primeRunnable1.start();
primeRunnable2.start();
primeRunnable3.start();
primeRunnable4.start();
}
}
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
public class PrimeRunnable implements Runnable {
// Static Util
public static List<PrimeRunnable> runningThreads = new CopyOnWriteArrayList<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();
}
}