JDK1.8 java.util.ConcurrentModificationException錯誤
阿新 • • 發佈:2018-11-26
一,示例程式碼:
List list = new ArrayList();
list.add(1);
list.add(2);
list.add(3);
Iterator it = list.iterate();
while(it.hasNext()) {
Object obj = it.next();
list.remove(1);
}
此時絕逼會拋java.util.ConcurrentModificationException錯誤,怎麼會呢,仔細檢視JDK,原來如此
注意,此實現不是同步的。如果多個執行緒同時訪問一個 ArrayList 例項,而其中至少一個執行緒從結構上修改了列表,那麼它必須 保持外部同步。(結構上的修改是指任何新增或刪除一個或多個元素的操作,或者顯式調整底層陣列的大小;僅僅設定元素的值不是結構上的修改。)這一般通過對自然封裝該列表的物件進行同步操作來完成。如果不存在這樣的物件,則應該使用 Collections.synchronizedList 方法將該列表“包裝”起來。這最好在建立時完成,以防止意外對列表進行不同步的訪問:List list = Collections.synchronizedList(new ArrayList(...));
此類的 iterator 和 listIterator 方法返回的迭代器是快速失敗的:在建立迭代器之後,除非通過迭代器自身的 remove 或 add 方法從結構上對列表進行修改,否則在任何時間以任何方式對列表進行修改,迭代器都會丟擲 ConcurrentModificationException。因此,面對併發的修改,迭代器很快就會完全失敗,而不是冒著在將來某個不確定時間發生任意不確定行為的風險。
二,解決辦法:
- // 1 使用Iterator提供的remove方法,用於刪除當前元素
- for (Iterator<String> it = myList.iterator(); it.hasNext();) {
- String value = it.next();
- if
- it.remove(); // ok
- }
- }
- System. out.println( "List Value:" + myList.toString());
- // 2 建一個集合,記錄需要刪除的元素,之後統一刪除
- List<String> templist = new ArrayList<String>();
- for (String value : myList) {
- if (value.equals( "3")) {
- templist.remove(value);
- }
- }
- // 可以檢視removeAll原始碼,其中使用Iterator進行遍歷
- myList.removeAll(templist);
- System. out.println( "List Value:" + myList.toString());
- // 3. 使用執行緒安全CopyOnWriteArrayList進行刪除操作
- List<String> myList = new CopyOnWriteArrayList<String>();
- myList.add( "1");
- myList.add( "2");
- myList.add( "3");
- myList.add( "4");
- myList.add( "5");
- Iterator<String> it = myList.iterator();
- while (it.hasNext()) {
- String value = it.next();
- if (value.equals( "3")) {
- myList.remove( "4");
- myList.add( "6");
- myList.add( "7");
- }
- }
- System. out.println( "List Value:" + myList.toString());
- // 4. 不使用Iterator進行遍歷,需要注意的是自己保證索引正常
- for ( int i = 0; i < myList.size(); i++) {
- String value = myList.get(i);
- System. out.println( "List Value:" + value);
- if (value.equals( "3")) {
- myList.remove(value); // ok
- i--; // 因為位置發生改變,所以必須修改i的位置
- }
- }
- System. out.println( "List Value:" + myList.toString());
這裡有很棒得一個總結