我有一个由多个线程操作的ArrayList,由于ArrayList未同步,因此无法正常工作。我按照教授的指示将列表切换为Vector。向量是同步的,但我有与同步相关的异常抛出。
为什么会发生这种情况,如何在代码中避免并发异常?我不想只是玩游戏直到有效,我想做最好的事情。谢谢!
例外:
Exception in thread "Thread-3" java.util.ConcurrentModificationException
at java.util.Vector$Itr.checkForComodification(Vector.java:1184)
at java.util.Vector$Itr.next(Vector.java:1137)
at BytePe4D$ReadInts.run(BytePe4D.java:64)
代码:
import java.io.*;
import java.util.Vector;
public class BytePe4D {
private Vector<Integer> numbers;
public static void main(String[] args) {
new BytePe4D();
}
public BytePe4D() {
// Create ArrayList and reset sum
numbers = new Vector<Integer>();
// Call addInts 8 times, with filenames integer1.dat through integer8.dat
for (int i = 1; i <= 8; i++) {
File file = new File("PE Data/integer" + i + ".dat");
ReadInts thread = new ReadInts(file);
thread.start();
}
}
/** Represents a Thread instance */
class ReadInts extends Thread {
File file;
public ReadInts(File _file) {
file = _file;
}
@Override
public void run() {
int count = 0; // track number of records read
int sum = 0;
try {
// Open stream to binary data file integer1.dat
FileInputStream in = new FileInputStream(file);
// Buffer the stream
BufferedInputStream bin = new BufferedInputStream(in);
// Access the primitive data
DataInputStream din = new DataInputStream(bin);
try {
// Read file until end reached
while (true) {
numbers.add(din.readInt());
count++;
}
} catch (EOFException eof) {
// System.out.println("End of file reached.");
} finally {
// Close streams
din.close();
}
} catch (FileNotFoundException fnf) {
System.out.println("File does not exist: " + file.getName());
return;
} catch (IOException ioe) {
ioe.printStackTrace();
}
// Calculate sum of numbers read
for (int num : numbers) {
sum += num;
}
// Write info
System.out.println(
String.format("%s%s%-5s%s%-8d%-5s%s%-12d%-5s%s%d",
"Filename = ", file.getName(), "",
"Count = ", count, "",
"Sum = ", sum, "",
"In List = ", numbers.size()));
}
}
}
答案 0 :(得分:5)
你的代码似乎错了。
如果每个线程要计算单个文件中的记录总和,我不明白为什么需要共享向量。另一方面,如果要计算所有文件中的记录总和,则应在每个线程完成后执行此操作。
根据您的需要,您可以1)为每个线程创建一个向量并计算每个文件的总和,或者2)在主线程中,等待所有线程完成,然后计算所有文件的总和。
答案 1 :(得分:3)
来自docs:
如果在迭代器之后的任何时间对结构进行了结构修改 以任何方式创建,除非通过迭代器自己删除或添加 方法,迭代器将抛出一个ConcurrentModificationException。
以下代码在封面下创建一个迭代器:
for (int num : numbers) {
sum += num;
}
因此,当一个线程修改向量(通过添加元素)而另一个向量迭代它时,您将看到ConcurrentModificationException
有不同的选项可以解决它,一种方法是从文件读取到另一个向量,当读取完成时,将另一个向量分配给numbers
(因为赋值是原子操作)。请注意,为了让更改对其他主题可见,您需要将numbers
声明为volatile
。