2015-08-15 62 views
0

我试图检查服务器的实体并每秒迭代它们,如果我找到一个不再生成的实体,它将自动重新生成。HashMap并发修改

问题发生在我的EntitySpawnEvent中,我从hashmap中删除旧实体并添加一个新实体,这会创建一个java.util.ConcurrentModificationException。有没有可能我至少压制这个错误? (因为我正在移除一个已经通过“检查”的实体。)

new BukkitRunnable() { 
     public void run() { 
      for(Entity e : CheckAliveEntities.keySet()) { 
       if(!(e.isValid())) { 
         if(!(e instanceof Player)) { 
          System.out.println("DA"); 
          x.removeHologram(e); 
          y.setEntityRespawn(e); 
          break; 
         } 
       } 
      } 
     }  
    }.runTaskTimer(this, 5, 5); 
+0

如果是多线程环境,则可以使用ConcurrentHashMap。如果单线程环境,你可以参考这篇文章http://stackoverflow.com/questions/2826380/concurrentmodificationexception-hashmap-in-java。 –

+0

add try {} catch {} block for for循环以上如果条件。有空的catch块来忽略异常。如果你想移动到其他集合框架,使用ConcurrentHashMap –

+0

谢谢你们,因为ConcurrentHashMap ideea,甚至不知道这些存在。你的答案是赢家xD。 –

回答

0

您可以使用迭代器来移除检测到要移除的实体。

new BukkitRunnable() { 
    public void run() { 
     for(Iterator<Entity> it = CheckAliveEntities.keySet().iterator(); it.hasNext();) { 
      Entity e = it.next(); 
      if (!e.isValid() && !(e instanceof Player)) { 
         System.out.println("DA"); 
         x.removeHologram(e); // needs refactoring 
         it.remove(); 
         y.setEntityRespawn(e); // needs refactoring 
         break; 
        } 
      } 
     } 
    }  
}.runTaskTimer(this, 5, 5); 

我不确定是removeHologram()还是setEntityRespawn()将删除实体。无论如何,我会重构逻辑,以便您可以删除for循环本身中的实体。尽管你可以选择将迭代器本身传递给这些方法,并在那里调用它.remove()。

如果您有多个正在运行的BukkitRunnable线程,并且它们都可以访问相同的HashMap,那么建议使用CheckAliveEntities的ConcurrentHashMap实现。请参阅http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ConcurrentHashMap.html