如何避免Java的ConcurrentModificationException ?
ConcurrentModificationException 是Java的一个预定义异常,它在我们使用Java集合时发生,即每当我们尝试在未经许可的情况下并发修改对象时,就会发生 ConcurrentModificationException,它存在于 Java的.util 包裹。
过程:为了避免在单线程环境中发生此异常,需要一些步骤。它们如下:
- 我们可以遍历数组,而不是遍历集合类。这对于较小的列表非常有效,对于较大的列表呢?我们知道,如果数组大小很大,那么它会影响性能,这是非常基本的。因此,此方法仅对较小尺寸的数组有效。
- 下一个方法是同步块方法,这里我们实际上将列表锁定在一个同步块中以避免异常。这不是很酷吗?但是猜猜这也不是避免异常的有效方法么?因为没有使用多线程的目的。
- 更好的方法是我们有 ConcurrentHashMap 和 CopyOnWriteArrayList 这是上述方法中最好的。
方法:
这里提出了两种方法,从最简单的方法开始,以达到目标的最佳方法结束。
- 使用循环:我们使用 Iterator remove() 方法而不是我们可以使用 for 循环来避免单线程环境中的 ConcurrentModificationException。如果我们添加任何额外的对象,那么我们可以确保我们的代码处理它们。
- 使用 remove() 方法:我们可以使用 remove 方法从集合中删除对象。这里有一个问题是您只能删除相同的对象,而不能从列表中删除任何其他对象
示例 1:
Java
// Java Program to Avoid
// AvoidConcurrentModificationException
// Importing Map and List utility classes
// from java.util package
import java.util.List;
import java.util.Map;
// Importing classes from java.util.concurrent package
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
// Main class
public class GFG {
// Main driver method
public static void main(String[] args)
{
// Creating an object of List class
// Declaring object of string type
List marvel
= new CopyOnWriteArrayList();
// Adding elements to the above object created
// Custom input entries
marvel.add("IronMan");
marvel.add("BlackWidow");
marvel.add("Hulk");
marvel.add("DoctorStrange");
marvel.add("SpiderMan");
// Iterating over object created using size() method
for (int i = 0; i < marvel.size(); i++) {
// Print and display the object elements
// using get() method
System.out.println("Avenger : "
+ marvel.get(i));
// Condition check over object elements
// If specific element is matched
if (marvel.get(i).equals("BlackWidow")) {
marvel.remove(i);
i--;
// Add this specific element
marvel.add("CaptianAmerica");
}
}
// Now getting the final total size by checking
// how many elements are there inside object
System.out.println("Total Avengers : "
+ marvel.size());
}
}
Java
// Java Program to Illustrate ConcurrentModificationException
// WithArrayListSubList
// Importing List and Arraylist classes utility classes
// from java.util package
import java.util.ArrayList;
import java.util.List;
// Main class
public class GFG {
// Main driver method
public static void main(String[] args) {
// Creating a List class object
// Declaring object of string type
List names = new ArrayList <>();
// Adding elements to the object of List class
// Custom input entries
names.add("Java");
names.add("C++");
names.add("Phython");
names.add("JavaScript");
List < String > first2Names = names.subList(0, 2);
System.out.println(names + " , " + first2Names);
names.set(1, "Ruby");
// check the output below. 🙂
System.out.println(names + " , " + first2Names);
// Now we add another string to
// get ConcurrentModificationException
names.add("SQL");
// This line throws an exception
System.out.println(names + " , " + first2Names);
}
}
输出
Avenger : IronMan
Avenger : BlackWidow
Avenger : Hulk
Avenger : DoctorStrange
Avenger : SpiderMan
Avenger : CaptianAmerica
Total Avengers :5
Note: The Exception can also occur if we try to modify the structure of original list with sublist. An example for the same is below,
示例 2:
Java
// Java Program to Illustrate ConcurrentModificationException
// WithArrayListSubList
// Importing List and Arraylist classes utility classes
// from java.util package
import java.util.ArrayList;
import java.util.List;
// Main class
public class GFG {
// Main driver method
public static void main(String[] args) {
// Creating a List class object
// Declaring object of string type
List names = new ArrayList <>();
// Adding elements to the object of List class
// Custom input entries
names.add("Java");
names.add("C++");
names.add("Phython");
names.add("JavaScript");
List < String > first2Names = names.subList(0, 2);
System.out.println(names + " , " + first2Names);
names.set(1, "Ruby");
// check the output below. 🙂
System.out.println(names + " , " + first2Names);
// Now we add another string to
// get ConcurrentModificationException
names.add("SQL");
// This line throws an exception
System.out.println(names + " , " + first2Names);
}
}
输出:
此后,我们讨论了如何在单线程和多线程环境中成功避免异常,如上述输出所示。