我认为我不能正确理解Java中的Vector是如何同步的。 在我的代码中,一些线程正在运行修改我的向量的指令,例如调用mVector.addAll(anothervector)。但是在使用以下代码对向量进行交互时,我的应用程序崩溃了:
// the vector declaration
Vector<myClass> mVector = new Vector<myClass>;
// the method that crashes
public void printVector(){
for (myClass mObject: mVector){
System.out.println(mObject);
}
}
如果Vector对象同步,为什么会崩溃?我该如何解决?提前致谢
答案 0 :(得分:6)
您没有指定“崩溃”的含义,但是如果您获得ConcurrentModificationException
,则表示另一个线程在for-each循环内部修改了您的列表。
此异常不表示同步问题本身,因为它可以在单个线程中复制(只需尝试在迭代时向列表中添加元素)。而是在迭代过程中修改集合的结构时抛出它。 Iterator
是有状态的;在使用它时修改集合会导致非常糟糕的错误,因此运行时可以防止它。
要修复它,你可以将for循环包装在synchronized块中:
synchronized (mVector) {
for (... ) {
}
}
答案 1 :(得分:2)
阅读Vector的文档:
Vector的iterator和listIterator方法返回的迭代器是快速失败的:如果在创建Iterator之后的任何时候对Vector进行结构修改,除了通过Iterator自己的remove或add方法之外,Iterator将抛出一个ConcurrentModificationException的。
该类是线程安全的,因为多个线程可以使用明确定义的行为同时读取/添加/删除元素。
迭代器也线程安全,因为它们永远不会返回被删除或无效的元素。
但这并不意味着你可以在从某个其他线程修改它时迭代一个向量。
答案 2 :(得分:0)
正在同步的矢量并不意味着,它将使我们免于对同步的误解。
import java.util.List;
import java.util.Vector;
public class Main {
public static void main(final String[] args) {
List<Integer> integers = new Vector<Integer>();
for (int i = 0; i < 10; i++) {
integers.add(i);
}
for (Integer integer : integers) {
integers.add(1); // this will raise ConcurrentModificationException
System.out.println(integer);
}
}
}
以上代码只会通过ConcurrentModificationException
。原因是,上面的代码试图迭代一个集合,此时它正试图更新自己。我们不可能同时做到。
如果你需要实现这样的东西,那么以某种方式标记/存储元素(例如:在列表中)并在完成迭代后更新向量(也是任何集合)。
修改强>
确保在printVector()
的foreach块内调用(非)mVector
方法,以摆脱ConcurrentModificationException
。