Войти или зарегистрироваться

Помогите Проблема с потоками (ConcurrentModificationException)

saharin94

Старожил
Заблокирован
Пользователь
Баллы
173
Имя в Minecraft
RubukkitDniwe
В общем есть плагин, который не даёт использовать нескольким игрокам болк одновременно (защита от кражи в ресурсообменниках). Всё бы хорошо, но периодически в консоли вылетает ConcurrentModificationException. Слышал об операторе synchronized, но не могу ума приложить где и как правильно (что в аргумент передавать) его использовать.

Фрагмент кода плагина:
Java:
public class DoubleInteract implements Listener {
  
  private HashMap<Block, Player>lockedBlocks;
  
  private void initCloseInvListener(){
    main.protocolManager.addPacketListener(new PacketAdapter(this.main, ConnectionSide.CLIENT_SIDE, ListenerPriority.HIGHEST, new Integer[]{Integer.valueOf(101)}){
      @Override
      public void onPacketReceiving(PacketEvent e){
         if(! config.doubleInteractEnable) return;
         final Player player = e.getPlayer();
         if(player == null) return;
         //synchronized(lockedBlocks){
           removePlayerLock(player); // удаляем из списка. Здесь вылетает исключение.
         //}
      }
    });
  }
  
   private void removePlayerLock(Player player){
     if(lockedBlocks.containsValue(player)){
       for(Block checkBlock : lockedBlocks.keySet()){
         if(player == lockedBlocks.get(checkBlock)){
           lockedBlocks.remove(checkBlock);
         }
       }
     }    
   }
  
  @EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
  public void onPlayerInteract(PlayerInteractEvent e) {
  if(e.getAction() != Action.RIGHT_CLICK_BLOCK) return;
  lockedBlocks.put(block, player); // вносим в список
  }

}
 
Можно сделать это, используя Iterator.delete().
 
Создай новый пустой список до итерирования, и заполняй его ключами в цикле тем, что хочешь удалить.
После цикла сделаешь ещё один цикл удаления.
Java:
        ArrayList<Block> removeThem = new ArrayList<>();
        for(Block checkBlock : lockedBlocks.keySet())
            if(player == lockedBlocks.get(checkBlock))
                removeThem.add(checkBlock);
        for(Block r : removeThem)
            lockedBlocks.remove(r);
 
Создай новый пустой список до итерирования, и заполняй его ключами в цикле тем, что хочешь удалить.
После цикла сделаешь ещё один цикл удаления.
Java:
        ArrayList<Block> removeThem = new ArrayList<>();
        for(Block checkBlock : lockedBlocks.keySet())
            if(player == lockedBlocks.get(checkBlock))
                removeThem.add(checkBlock);
        for(Block r : removeThem)
            lockedBlocks.remove(r);
Зачем такие костыли?
 
Создай новый пустой список до итерирования, и заполняй его ключами в цикле тем, что хочешь удалить.
После цикла сделаешь ещё один цикл удаления.
Java:
        ArrayList<Block> removeThem = new ArrayList<>();
        for(Block checkBlock : lockedBlocks.keySet())
            if(player == lockedBlocks.get(checkBlock))
                removeThem.add(checkBlock);
        for(Block r : removeThem)
            lockedBlocks.remove(r);
Да вы просто мастер вредных советов.
 
В крайнем случае можно перебирать созданием счетчика:

for (int i = 0; i < size; i++) {
И тут перебор с удалением.
}
 
Назад
Верх