2015-08-15 98 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