1

はい、この質問が存在すると確信していますが、回答を試してみましたが、カスタム回答が必要だと思います..

とにかく、タイトルが示唆しているように、私は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;
    }

}

他に何が必要か教えてください。

4

2 に答える 2

1

EventCallerクラスでメソッドを確認してくださいpublic void call(ArrayList<Listener> listeners, Event e)

for ループの内部

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

h は、反復が完了する前に修飾子を取得しています。具体的にはm.invoke(h, (Type) e);、 call が何をするかを確認してください。h を変更してはなりません。

于 2013-08-28T03:48:52.297 に答える
0

回答 1: list.toArray() を使用してリストを配列に変換し、配列を反復処理できます。リストが大きい場合、この方法はお勧めできません。

回答 2: コードを同期ブロック内にラップすることにより、反復中にリスト全体をロックできます。このアプローチは、アプリケーションの同時実行が多い場合、アプリケーションのスケーラビリティに悪影響を及ぼします。

回答 3: JDK 1.5 は ConcurrentHashMap および CopyOnWriteArrayList クラスを提供します。これにより、スケーラビリティが大幅に向上し、ConcurrentHashMap.iterator() によって返される反復子は、スレッド セーフを維持しながら ConcurrentModificationException をスローしません。

回答 4: 基になるコレクション「myStr」への参照を持つイテレータ「it」を介して現在のオブジェクトを削除します。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();

         }
     }
  }

}

于 2013-08-28T03:50:49.690 に答える