Java 在遍历对象时从列表中删除对象

Java 在遍历对象时从列表中删除对象,java,arraylist,linked-list,hashmap,Java,Arraylist,Linked List,Hashmap,我目前正在制作一个游戏,要编辑/删除/添加我的所有实体,我有一个数组列表。每一帧每秒60倍更新和渲染列表中的所有内容。当我在entities update方法中调用要添加或删除的对象时,我在Thread-2中收到一个错误。通过一些快速的研究,我发现在迭代列表时编辑列表是不正确的。这就是我目前遇到的问题吗?还是因为我的列表不是线程安全的 渲染方法: public void render(Graphics g){ for(Entity entity: list){ en

我目前正在制作一个游戏,要编辑/删除/添加我的所有实体,我有一个数组列表。每一帧每秒60倍更新和渲染列表中的所有内容。当我在entities update方法中调用要添加或删除的对象时,我在Thread-2中收到一个错误。通过一些快速的研究,我发现在迭代列表时编辑列表是不正确的。这就是我目前遇到的问题吗?还是因为我的列表不是线程安全的

渲染方法:

public void render(Graphics g){
     for(Entity entity: list){
          entity.render(g);
      }
 }
更新方法:

public void update(){
     for(Entity entity: list){
          entity.update();
      }
 }
如果我的问题是在更新列表时编辑列表,这是如何解决的

public void update(){
     for(Entity entity: list){
          entity.update();
      }

     for(Entity entity: removeList){
          list.remove(entity);
      }
      removeList.clear();
 }
还是因为我的列表不是线程安全的

是,如果渲染和更新可以在不同线程上同时运行

这是怎么解决的

不,仍然是相同的问题,您将尝试在迭代时删除

或者

构建一个新列表,其中只包含要保留的条目,然后将其替换为更新对象引用的列表是原子的,或者

同步列表中渲染和更新方法的相关部分

下面是1的一个粗略示例:

public void update(){

    List newList = new AppropriateListType(list);
    for (Entity entity : removeList){
        newList.remove(entity);
    }
    removeList.clear(); // Or removeList = new AppropriateListType();
    list = newList;

    for (Entity entity: list) {
        entity.update();
    }
}
注:我颠倒了这两个循环的顺序;大概在更新您将要删除的实体时没有什么意义

这是因为在我们修改新列表时,没有任何东西可以尝试迭代它,因为在我们执行list=newList之前,新列表对于update方法的这个特定执行是完全私有的。一旦我们执行list=newList,它就在对象上,所以其他代码将尝试使用它

还有一个粗略的例子2:

public void update(){
    synchronized (list) {
        for (Entity entity: removeList){
            list.remove(entity);
        }
    }
    removeList.clear();

    for (Entity entity: list) {
        // This is probably fine depending on how `render` and `update` work
        // but you *may* need to `synchronize` on `entity` (here and in `render`
        // depending on how `render` and `update` work
        entity.update();
    }
}
同样,循环是反向的

有关中同步的详细信息


旁注:您可能还需要检查removeList的迭代和更新。

Crowder如果我的列表不安全,是否可以使用其他线程类型?我将如何同步列表中的相关部分?@MaxwellBrookes-您将执行我上面描述的操作…?ArrayList是合适的列表类型吗?或者它必须是一个同步的列表?@MaxwellBrookes-如果你在做上面的事情,不需要使用其中一个内置同步的列表。因此,无论什么列表类型适合您所做的事情。您得到的确切错误消息是什么?哪一行导致它?寻求调试帮助的问题为什么这段代码不起作用?必须包括所需的行为、特定的问题或错误以及在问题本身中重现这些问题所需的最短代码。没有明确问题陈述的问题对其他读者没有用处。请参见:如何创建。使用链接改进您的问题-不要通过评论添加更多信息。谢谢