Vector
Vector在迭代器遍历时,其他线程增删元素,会抛ConcurrentModificationException。
public class Main {
public static void main(String[] args) {
List<Integer> list = new Vector<>(Arrays.asList(1, 2, 3, 4, 5));
ExecutorService executorService = Executors.newFixedThreadPool(3);
executorService.execute(() -> {
while (true) {
for (Integer e : list) {
System.out.println(e);
}
}
});
executorService.execute(() -> {
for (int i = 0; i < 100; ++i) {
list.add(i);
}
});
}
}
运行结果:

Vector迭代器没有创建拷贝,直接在存储元素的数组上迭代。
final void checkForComodification() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
每次迭代前,都会检查是否在其他线程进行过增删,如果有,直接抛出ConcurrentModificationException。
Collections.synchronizedList
和Vector一样,会抛ConcurrentModificationException。
public class Main {
public static void main(String[] args) {
List<Integer> list = Collections.synchronizedList(
new ArrayList<>(Arrays.asList(1, 2, 3, 4, 5)));
ExecutorService executorService = Executors.newFixedThreadPool(3);
executorService.execute(() -> {
while (true) {
for (Integer e : list) {
System.out.println(e);
}
}
});
executorService.execute(() -> {
for (int i = 0; i < 100; ++i) {
list.add(i);
}
});
}
}
运行结果:

Collections.synchronizedList直接使用的是被包装list自生的迭代器。在我们这个例子中使用的就是ArrayList的迭代器。像ArryaList、LinkedList这些,在迭代时,其他线程增删,都会抛ConcurrentModificationException。
public Iterator<E> iterator() {
return c.iterator(); // Must be manually synched by user!
}
CopyOnWriteArrayList
CopyOnWriteArrayList是在创建迭代器时的数组快照(这个数组上不会有增删改任何写操作)上迭代的,不会抛ConcurrentModificationException。
public E next() {
if (! hasNext())
throw new NoSuchElementException();
return (E) snapshot[cursor++];
}
网友评论