📜  Java中的 ConcurrentModificationException 和示例

📅  最后修改于: 2022-05-13 01:55:48.842000             🧑  作者: Mango

Java中的 ConcurrentModificationException 和示例

多线程环境中的 ConcurrentModificationException

多线程环境中,如果在资源检测过程中,任何方法发现该对象存在不允许的并发修改,则可能会抛出此 ConcurrentModificationException。

  1. 如果检测到此异常,则迭代的结果未定义。
  2. 通常,一些迭代器实现选择在遇到此异常时立即抛出,称为快速失败迭代器。

例如:如果我们试图使用一个线程修改代码中的任何集合,但另一个线程已经在使用该集合,那么这将是不允许的。

单线程环境中的 ConcurrentModificationException

由于无法保证每当引发此异常时,某个对象正在被某个不同的线程同时修改,因此在单线程环境中也会引发此异常。

如果我们在违反其契约的对象上调用一系列方法,则该对象将抛出 ConcurrentModificationException。

例如:如果在迭代集合时,我们直接尝试修改该集合,那么给定的快速失败迭代器将抛出这个 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 arr
            = new ArrayList();
  
        arr.add("One");
        arr.add("Two");
        arr.add("Three");
        arr.add("Four");
  
        try {
            // Printing the elements
            System.out.println(
                "ArrayList: ");
            Iterator 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?

为避免此异常,

  • 简单地说,我们可以在迭代完成后进行修改,或者
  • 实现同步块或方法的概念

示例:让我们看看如何通过简单地更改修改位置来解决此异常。

// 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 arr
            = new ArrayList();
  
        arr.add("One");
        arr.add("Two");
        arr.add("Three");
        arr.add("Four");
  
        try {
            // Printing the elements
            System.out.println(
                "ArrayList: ");
            Iterator 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。