1. Этот сайт использует файлы cookie. Продолжая пользоваться данным сайтом, Вы соглашаетесь на использование нами Ваших файлов cookie. Узнать больше.
  2. Вы находитесь в сообществе Rubukkit. Мы - администраторы серверов Minecraft, разрабатываем собственные плагины и переводим на различные языки плагины наших коллег из других стран.
    Скрыть объявление
Скрыть объявление
В преддверии глобального обновления, мы проводим исследования, которые помогут нам сделать опыт пользования форумом ещё удобнее. Помогите нам, примите участие!

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

Тема в разделе "Разработка плагинов для новичков", создана пользователем saharin94, 19 авг 2014.

  1. Автор темы
    saharin94

    saharin94 Старожил Пользователь Заблокирован

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

    Фрагмент кода плагина:
    Код:
    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); // вносим в список
      }
    
    }
     
  2. Den_Abr

    Den_Abr Старожил Девелопер Пользователь

    Баллы:
    173
    Skype:
    Den_Abr
    Имя в Minecraft:
    Den_Abr
    Вы не можете удалять элементы коллекции во время её итерации
     
  3. serega6531

    serega6531 Старожил Девелопер Пользователь

    Баллы:
    173
    Skype:
    shkurovs
    Можно сделать это, используя Iterator.delete().
     
  4. Автор темы
    saharin94

    saharin94 Старожил Пользователь Заблокирован

    Баллы:
    173
    И где его нужно использовать?
     
  5. serega6531

    serega6531 Старожил Девелопер Пользователь

    Баллы:
    173
    Skype:
    shkurovs
    Нужно делать итерацию через итератор, а не через for( : ), и в нужный момент использовать iter.remove().
     
  6. ptnk

    ptnk Старожил Пользователь

    Баллы:
    173
    Я тебе скажу по секрету, что в for( : ) идёт обход тоже через итератор.
     
  7. serega6531

    serega6531 Старожил Девелопер Пользователь

    Баллы:
    173
    Skype:
    shkurovs
    Я и не спорю, но обращаться к нему нельзя же.
     
  8. ptnk

    ptnk Старожил Пользователь

    Баллы:
    173
    Я всего лишь указал на неточность формулировки.
     
  9. Reality_SC

    Reality_SC Старожил Пользователь

    Баллы:
    123
    Имя в Minecraft:
    Reality_SC
    Создай новый пустой список до итерирования, и заполняй его ключами в цикле тем, что хочешь удалить.
    После цикла сделаешь ещё один цикл удаления.
    Код:
            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);
    
     
  10. serega6531

    serega6531 Старожил Девелопер Пользователь

    Баллы:
    173
    Skype:
    shkurovs
    Зачем такие костыли?
     
  11. Shevchik

    Shevchik Старожил Пользователь

    Баллы:
    173
    Имя в Minecraft:
    _Shevchik_
    Да вы просто мастер вредных советов.
     
  12. Reality_SC

    Reality_SC Старожил Пользователь

    Баллы:
    123
    Имя в Minecraft:
    Reality_SC
    Да, наверное :) Почему бы и нет :)
     
  13. kirill2011s

    kirill2011s Старожил Пользователь

    Баллы:
    103
    В крайнем случае можно перебирать созданием счетчика:

    for (int i = 0; i < size; i++) {
    И тут перебор с удалением.
    }
     
  14. Автор темы
    saharin94

    saharin94 Старожил Пользователь Заблокирован

    Баллы:
    173
    :facepalm:
     
  15. JustBlender

    JustBlender Старожил Девелопер Пользователь

    Баллы:
    123
    Skype:
    justblender
    Имя в Minecraft:
    JustBlender
    А почему бы и нет?
     
  16. Shevchik

    Shevchik Старожил Пользователь

    Баллы:
    173
    Имя в Minecraft:
    _Shevchik_
    Ну ну. Попробуй.
     
  17. JustBlender

    JustBlender Старожил Девелопер Пользователь

    Баллы:
    123
    Skype:
    justblender
    Имя в Minecraft:
    JustBlender
    Если я это и использовал с листами, проблем не было никаких.
     
  18. Shevchik

    Shevchik Старожил Пользователь

    Баллы:
    173
    Имя в Minecraft:
    _Shevchik_
    И где ты тут лист видишь?
     
  19. JustBlender

    JustBlender Старожил Девелопер Пользователь

    Баллы:
    123
    Skype:
    justblender
    Имя в Minecraft:
    JustBlender
    Да йобана, не заметил.
     

Поделиться этой страницей