2013-08-28 6 views
1

Да я уверен, что этот вопрос существует, но я попробовал ответы, и я предполагаю, что я нужен пользовательского ответа ..Java Событие - java.util.ConcurrentModificationException

Во всяком случае, как название предлагает 'получение java.util.ConcurrentModificationException.

Все это называется в его собственной теме.

Как запускать события:

private void setUpMainGameTimer() { 
     Timer timer = new Timer(); 
     timer.schedule(new TimerTask() { 
      @Override 
      public void run() { 
       try{ 
        TickEvent.call(); 
       } catch (Exception e){ 
        e.printStackTrace(); 
       } 
      } 
     }, 0, gameSpeed); 
    } 

Мой трассировки стека.

java.util.ConcurrentModificationException 
    at java.util.ArrayList$Itr.checkForComodification(Unknown Source) 
    at java.util.ArrayList$Itr.next(Unknown Source) 
    at net.njar.rpg.Event.EventCaller.call(EventCaller.java:15) 
    at net.njar.rpg.Event.TickEvent.call(TickEvent.java:10) 
    at net.njay.rpg.Main.Main$1.run(Main.java:213) 
    at java.util.TimerThread.mainLoop(Unknown Source) 
    at java.util.TimerThread.run(Unknown Source) 

Это мой класс EventCaller.

public class EventCaller<Type extends Event> { 

    @SuppressWarnings("unchecked") 
    public void call(ArrayList<Listener> listeners, Event e){ 
     //Iterate through all of the listeners 
     for (Listener h : listeners){ 

      //Iterate through each method 
      for (Method m : h.getClass().getMethods()){ 
       //check if @EventHandler is present 
       if (m.isAnnotationPresent(EventHandler.class)){ 
        //get params 
        for (Class<?> param : m.getParameterTypes()){ 
         //check if parameter is the same type as the passed event 
         if (param.equals(e.getClass())) { 
          try { 
           m.invoke(h, (Type) e); 
          } catch(Exception e1){ 
           e1.printStackTrace(); 
          } 
         } 

        } 
       } 
      } 
     } 
    } 
} 

И отметьте событие:

public class TickEvent extends Event{ 
    private static long id = 0; 

    public static void call(){ 
     id++; 
     TickEvent e = new TickEvent(); 
     EventCaller<TickEvent> caller = new EventCaller<TickEvent>(); 
     caller.call(Event.getListeners(), e); 
    } 

    public long getTickID(){ 
     return TickEvent.id; 
    } 

    public static long getcurrentTickID(){ 
     return id; 
    } 
} 

Класс событий:

public class Event { 

    private static ArrayList<Listener> listeners = new ArrayList<Listener>(); 

    public static void addListener(Listener listener){ 
     listeners.add(listener); 
    } 

    public synchronized static ArrayList<Listener> getListeners(){ 
     return Event.listeners; 
    } 

} 

Просто дайте мне знать, что еще вам нужно.

+0

Где код для метода аннотацией '@ EventHandler'? – Bohemian

+0

Возможный дубликат [ConcurrentModificationException даже с использованием Collections.sychronizedMap на LinkedHashMap] (http://stackoverflow.com/questions/18343989/concurrentmodificationexception-even-with-using-collections-sychronizedmap-on-a) – yshavit

+0

Я сильно подозреваю, что нить - красная селедка; является одним из обратных вызовов, изменяющих коллекцию 'listeners'? – yshavit

ответ

0

В EventCaller Класс проверяет ваш метод public void call(ArrayList<Listener> listeners, Event e).

Внутри для цикла

for (Listener h : listeners){...} 

ч получает модификатор до итерации. В частности, проверьте, что делает вызов m.invoke(h, (Type) e);. Он не должен изменять h.

0

Ответ 1: Список может быть преобразован в массив с list.toArray() и итерацией по массиву. Этот подход не является рекомендуется, если список большой.

Ответ 2: Весь список можно заблокировать во время итерации, завернув код в синхронизированный блок. Этот подход отрицательно сказывается на масштабируемости вашего приложения, если он сильно параллелен.

Ответ 3: JDK 1.5 предоставляет классы ConcurrentHashMap и CopyOnWriteArrayList, которые обеспечивают гораздо лучшую масштабируемость, и итератор, возвращаемый ConcurrentHashMap.iterator(), не будет бросать ConcurrentModificationException при сохранении безопасности потоков.

Ответ 4: Удалите текущий объект через Итератор «он», который имеет ссылку на базовую коллекцию «myStr». Объект Iterator предоставляет для этого метод it.remove().

public class EventCaller<Type extends Event> { 

    @SuppressWarnings("unchecked") 
    public void call(ArrayList<Listener> listeners, Event e){ 

     //Iterate through all of the listeners 
     for(Iterator<Listener> iter = listeners.iterator(); iter.hasNext();) { 
      Listener h = iter.next(); 

     } 
    } 
    } 

}

Смежные вопросы