多線程環境中的ConcurrentModificationException
在多線程環境中,如果在檢測資源的過程中,任何方法發現存在不允許的並發修改,則可能會拋出ConcurrentModificationException。
- 如果檢測到此異常,則迭代的結果是不確定的。
- 通常,一些迭代器實現選擇在遇到此異常時立即拋出,稱為fail-fast iterators 。
例如:如果我們嘗試使用線程修改代碼中的任何集合,但另一個線程已經在使用該集合,那麽這是不允許的。
單線程環境中的ConcurrentModificationException
由於無法保證每當引發此異常時,對象都會被某個不同的線程並發修改,因此在單線程環境中也會引發此異常。
如果我們在一個對象上調用一係列違反其約定的方法,那麽該對象將拋出 ConcurrentModificationException。
例如:如果在迭代集合時,我們直接嘗試修改該集合,則給定的fail-fast 迭代器將拋出此 ConcurrentModificationException。
例子:在以下代碼中,實現了ArrayList。然後在遍曆時添加很少的值並且對其進行很少的修改,
// Java program to show
// ConcurrentModificationException
import java.util.Iterator;
import java.util.ArrayList;
public class modificationError {
public static void main(String args[])
{
// Creating an object of ArrayList Object
ArrayList<String> arr
= new ArrayList<String>();
arr.add("One");
arr.add("Two");
arr.add("Three");
arr.add("Four");
try {
// Printing the elements
System.out.println(
"ArrayList: ");
Iterator<String> iter
= arr.iterator();
while (iter.hasNext()) {
System.out.print(iter.next()
+ ", ");
// ConcurrentModificationException
// is raised here as an element
// is added during the iteration
System.out.println(
"\n\nTrying to add"
+ " an element in "
+ "between iteration\n");
arr.add("Five");
}
}
catch (Exception e) {
System.out.println(e);
}
}
}
輸出:
ArrayList: One, Trying to add an element in between iteration java.util.ConcurrentModificationException
如何避免ConcurrentModificationException?
為了避免這種異常,
- 簡單地,我們可以在迭代完成後進行修改,或者
- 實施synchronized block or method的概念
例子:我們來看看如何通過簡單改變修改的地方來解決這個異常。
// Java program to show
// ConcurrentModificationException
import java.util.Iterator;
import java.util.ArrayList;
public class modificationError {
public static void main(String args[])
{
// Creating an object of ArrayList Object
ArrayList<String> arr
= new ArrayList<String>();
arr.add("One");
arr.add("Two");
arr.add("Three");
arr.add("Four");
try {
// Printing the elements
System.out.println(
"ArrayList: ");
Iterator<String> iter
= arr.iterator();
while (iter.hasNext()) {
System.out.print(iter.next()
+ ", ");
}
// No exception is raised as
// a modification is done
// after the iteration
System.out.println(
"\n\nTrying to add"
+ " an element in "
+ "between iteration: "
+ arr.add("Five"));
// Printing the elements
System.out.println(
"\nUpdated ArrayList: ");
iter = arr.iterator();
while (iter.hasNext()) {
System.out.print(iter.next()
+ ", ");
}
}
catch (Exception e) {
System.out.println(e);
}
}
}
輸出:
ArrayList: One, Two, Three, Four, Trying to add an element in between iteration: true Updated ArrayList: One, Two, Three, Four, Five,
從輸出中可以清楚地看到,隻需對代碼進行最小的更改,就可以消除ConcurrentModificationException。
相關用法
- Java ConcurrentMap用法及代碼示例
- Java ConcurrentHashMap computeIfPresent()用法及代碼示例
- Java ConcurrentHashMap equals()用法及代碼示例
- Java ConcurrentHashMap forEach()用法及代碼示例
- Java ConcurrentHashMap getOrDefault()用法及代碼示例
- Java ConcurrentHashMap hashcode()用法及代碼示例
- Java ConcurrentHashMap mappingCount()用法及代碼示例
- Java ConcurrentHashMap merge()用法及代碼示例
- Java ConcurrentHashMap newKeySet()用法及代碼示例
- Java ConcurrentHashMap replace()用法及代碼示例
- Java ConcurrentHashMap toString()用法及代碼示例
- Java ConcurrentLinkedQueue forEach()用法及代碼示例
- Java ConcurrentLinkedQueue removeAll()用法及代碼示例
- Java ConcurrentLinkedQueue removeIf()用法及代碼示例
- Java ConcurrentLinkedQueue retainAll()用法及代碼示例
- Java ConcurrentHashMap contains()用法及代碼示例
- Java ConcurrentHashMap containsKey()用法及代碼示例
- Java ConcurrentHashMap containsValue()用法及代碼示例
- Java ConcurrentHashMap elements()用法及代碼示例
- Java ConcurrentHashMap entrySet()用法及代碼示例
- Java ConcurrentHashMap get()用法及代碼示例
- Java ConcurrentHashMap isEmpty()用法及代碼示例
- Java ConcurrentHashMap keys()用法及代碼示例
- Java ConcurrentHashMap keySet()用法及代碼示例
- Java ConcurrentHashMap put()用法及代碼示例
注:本文由純淨天空篩選整理自sanskar_bindal大神的英文原創作品 ConcurrentModificationException in Java with Examples。非經特殊聲明,原始代碼版權歸原作者所有,本譯文未經允許或授權,請勿轉載或複製。