尽管已同步,但 Vector 仍抛出 ConcurrentModificationException
Vector throws ConcurrentModificationException despite being synchronized
我有一个由多个线程操作的 ArrayList,由于 ArrayList 未同步,它无法正常工作。我按照教授的指示将列表切换为 Vector。 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()));
}
}
}
您的代码似乎有误。
如果每个线程要计算单个文件的记录总和,我不明白您为什么需要共享向量。另一方面,如果你想计算所有文件的记录总和,你应该在每个线程完成后计算。
根据需要,您可以 1) 为每个线程创建一个向量并计算每个文件的总和,或者 2) 在主线程中,等待所有线程完成,然后计算所有线程的总和文件。
来自docs:
if the vector is structurally modified at any time after the iterator
is created, in any way except through the iterator's own remove or add
methods, the iterator will throw a ConcurrentModificationException.
以下代码在幕后创建了一个迭代器:
for (int num : numbers) {
sum += num;
}
所以当一个线程修改向量(通过添加元素)而另一个向量迭代它时 - 你会看到 ConcurrentModificationException
有不同的解决方案,一种方法是从文件读取到另一个向量,读取完成后将另一个向量分配给 numbers
(因为分配是原子操作)。请记住,为了让更改对其他线程可见,您需要将 numbers
声明为 volatile
.
我有一个由多个线程操作的 ArrayList,由于 ArrayList 未同步,它无法正常工作。我按照教授的指示将列表切换为 Vector。 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()));
}
}
}
您的代码似乎有误。
如果每个线程要计算单个文件的记录总和,我不明白您为什么需要共享向量。另一方面,如果你想计算所有文件的记录总和,你应该在每个线程完成后计算。
根据需要,您可以 1) 为每个线程创建一个向量并计算每个文件的总和,或者 2) 在主线程中,等待所有线程完成,然后计算所有线程的总和文件。
来自docs:
if the vector is structurally modified at any time after the iterator is created, in any way except through the iterator's own remove or add methods, the iterator will throw a ConcurrentModificationException.
以下代码在幕后创建了一个迭代器:
for (int num : numbers) {
sum += num;
}
所以当一个线程修改向量(通过添加元素)而另一个向量迭代它时 - 你会看到 ConcurrentModificationException
有不同的解决方案,一种方法是从文件读取到另一个向量,读取完成后将另一个向量分配给 numbers
(因为分配是原子操作)。请记住,为了让更改对其他线程可见,您需要将 numbers
声明为 volatile
.