在Java中,同步容器主要包括2類:java
Collections.synchronizedCollection(Collection<T> c) Collections.synchronizedSet(Set<T> s) Collections.synchronizedList(List<T> list) Collections.synchronizedMap(Map<K,V> m)
同步容器的缺陷:數組
對Vector、ArrayList在迭代的時候若是同時對其進行修改就會拋出java.util.ConcurrentModificationException異常。即:安全
public class Test { public static void main(String[] args) { ArrayList<Integer> list = new ArrayList<Integer>(Arrays.asList(1,2)); Iterator<Integer> iterator = list.iterator(); while(iterator.hasNext()){ Integer integer = iterator.next(); if(integer == 2) list.remove(integer); } } }
結果拋出異常:java.util.ConcurrentModificationException多線程
一樣併發
for(Integer i: list){ if(2 == i){ list.remove(i); } }
也會拋出異常。性能
可是有一點,java7下,要修改的元素不是list的最後一位則不會拋異常,不懂。線程
ArrayList<Integer> list = new ArrayList<Integer>(Arrays.asList(1,2,3)); Iterator<Integer> iterator = list.iterator(); while(iterator.hasNext()){ Integer integer = iterator.next(); if(integer == 2) list.remove(integer); }
上面這種狀況不會拋出異常。code
// TODO 分析源碼繼承
緣由:調用list.remove()方法致使modCount和expectedModCount的值不一致。接口
(1)調用Iterator.remove()
public class Test { public static void main(String[] args) { ArrayList<Integer> list = new ArrayList<Integer>(Arrays.asList(1,2)); Iterator<Integer> iterator = list.iterator(); while(iterator.hasNext()){ Integer integer = iterator.next(); if(integer == 2) iterator.remove(); //注意這個地方 } } }
(2)額外使用list保存要刪除的元素
ArrayList<Integer> list = new ArrayList<>(Arrays.asList(1,2)); Iterator<Integer> iterator = list.iterator(); ArrayList<Integer> toRemove = new ArrayList<>(); while (iterator.hasNext()){ Integer integer = iterator.next(); if(integer == 2){ toRemove.add(integer); } } list.removeAll(toRemove);
上述方法中的第一種,在多線程下並不適用。無論使用的是ArrayList仍是線程安全的Vector,均可能會拋出異常。
一般的兩種解決辦法: