Java ConcurrentModificationException具有全局变量,但不具有局部变量

Java ConcurrentModificationException具有全局变量,但不具有局部变量,java,global-variables,local-variables,concurrentmodification,Java,Global Variables,Local Variables,Concurrentmodification,在下面的函数中,我声明了局部变量allPeopel和itr(它们是覆盖全局变量)。如果我注释掉局部变量(在下面的两个函数之间),则会抛出ConcurrentModificationError。但是,如果我使用局部变量而不是全局变量,那么代码就可以正常工作。我不明白为什么会这样?这个类中还有很多其他函数,所以我尝试使用全局变量来实现更高效的代码 public void removeAPerson(){ int id; Scanner sc = new Scan

在下面的函数中,我声明了局部变量
allPeopel
itr
(它们是覆盖全局变量)。如果我注释掉局部变量(在下面的两个函数之间),则会抛出ConcurrentModificationError。但是,如果我使用局部变量而不是全局变量,那么代码就可以正常工作。我不明白为什么会这样?这个类中还有很多其他函数,所以我尝试使用全局变量来实现更高效的代码

   public void removeAPerson(){
        int id;
        Scanner sc = new Scanner(System.in);
        System.out.print("Enter ID of person to delete > ");
        id = sc.nextInt();
        sc.nextLine();
        System.out.println();

        /*************************************/
        ArrayList<Person> allPeople;
        allPeople = Person.getAllPeople();
        Iterator itr = allPeople.iterator();
        /*************************************/

        while(itr.hasNext()){
            Person obj = (Person) itr.next();
            int ID = obj.getID2();
            if(ID == id){
                itr.remove();
                break;
            }
        }
    }
public void removeAPerson(){
int-id;
扫描仪sc=新的扫描仪(System.in);
系统输出打印(“输入要删除的人的ID>”;
id=sc.nextInt();
sc.nextLine();
System.out.println();
/*************************************/
ArraylistAllPeople;
allPeople=Person.getAllPeople();
迭代器itr=allPeople.Iterator();
/*************************************/
while(itr.hasNext()){
Person obj=(Person)itr.next();
int ID=obj.getID2();
if(ID==ID){
itr.remove();
打破
}
}
}

使用局部变量,每次线程调用您的方法时,都会创建这些变量的新实例,这些变量对任何其他线程都不可用(除非您特别允许传递引用)。因此,没有其他线程可以修改您的对象


使用全局(我认为您的意思是
实例
变量、属性),所有访问对象的线程都可以访问对象的那些属性(让它直接访问,让它通过运行对象方法访问),并且可以在另一个线程运行迭代时修改它们。由于
迭代器
可以检测正在迭代的
集合
何时被修改,因此当发生这种情况时,它会抛出异常(这意味着“我正在迭代集合的所有对象,但这些对象不再相同,因此这太混乱,我失败了”.

这是你可能拥有的东西的草图:

public class MyClass {
  List<Person> persons = new ArrayList<>();
  Iterator<Person> iter = strs.iterator();

  public void addPerson(Person p) {
    persons.add(p);
  }

  public void removePerson() {
    ... your posted code ...
  }


  public static void main(String... args) {
    MyClass c = new MyClass();
    c.addPerson(new Person());
    c.removePerson();
  }
公共类MyClass{
List persons=new ArrayList();
迭代器iter=strs.Iterator();
公众人士(p人){
增加(p);
}
公共无效删除人(){
…您发布的代码。。。
}
公共静态void main(字符串…参数){
MyClass c=新的MyClass();
c、 addPerson(newperson());
c、 removePerson();
}
发生的情况是,您只实例化迭代器一次,然后向列表中添加一些内容,然后使用迭代器。像这样重用迭代器的全局实例是没有意义的。具体地说,在实例化它之后,除非通过迭代器本身,否则不能更改列表


使用全局变量是一回事,但使用迭代器的全局实例是另一回事。两者都是错误的,但后者是致命的。

使用全局变量,您的代码肯定不会更有效率。不过,这将更容易出错,而且是维护的噩梦。最后,唯一的方向是由于堆变量的读取速度比堆栈/寄存器变量的读取速度慢,因此全局变量的性能可能会发生变化。谢谢@MarkoTopolnik。我会坚持使用局部变量。我仍然想理解为什么全局变量而非局部变量会引发错误?可能是两个方法试图同时更新同一个列表?没有s查看您的全局实现很难猜测。几乎每次出现编程错误时都会出现一个非本地迭代器。@Nambari只有一个线程,因此我认为两个方法不能同时访问列表。谢谢。这对我现在来说很有意义。我指的是
global
我指的是
instance
。我不确定是否完全理解您的意思。我只有一个线程,但我不认为这就是你的意思。由于切换,我可以使用不同的路径,这就是你所说的不同线程吗?我感到困惑的原因是,即使不同的函数可以操作ArrayList,但一次只能有一个线程可以访问。好吧,我不认为你的迭代器会e也有一个实例属性(正如Marko所说,这根本没有意义),所以我假设集合的修改必须在某个时刻由另一个线程中运行的其他代码完成。所以我假设您的代码是正确的(事实并非如此)这只留下了修改其他线程的选项。谢谢。这是我第一次遇到迭代器。这对我来说很有意义