1

なぜこのコードは:

public synchronized void update() {
        for(T event : eventQueue)
        {
            processEvent(event);
        }
        events = eventQueue;
        eventQueue = new LinkedList<T>();
}

このコードとは異なる方法で実行します:

public synchronized void update() {
            for(T event : eventQueue)
            {
                processEvent(event);
            }
            events = eventQueue;
            eventQueue.clear();
}

最初のバージョンは問題なく動作しますが、2 番目のバージョンは機能しません。これeventQueue.clear();により、アプリはイベントを受信せず、Concurrent Exception.

私のアプリには 2 つのスレッドがあります。UI スレッドと GameLoop スレッド。UI スレッドはイベントを次のeventQueueように追加します。

public synchronized void addEvent(T newEvent) {
            eventQueue.add(newEvent);
}

GameLoop スレッドは update メソッドを呼び出してeventseventQueue.

すべてのコードは、次の Web サイトから表示できます: http://entropyinteractive.com/2011/02/game-engine-design-input/

と の両方が空の結果になるeventQueue = new LinkedList<T>();と思ったので、これは私にはちょっと不思議に思えます? 私はそれが新しい参照を確立することと関係があると信じています (しかし、なぜ?!)。eventQueue.clear();LinkedList

4

3 に答える 3

3

このコードでは:

public LinkedList<T> getEvents()
{
    return events;
}

コピーではなく、元のリストを返します。次にclear()そのリストを使用すると、他のスレッドがそれを使用している間にリストから物を削除する (さらに重要なことに、リストのサイズを変更する) ため、問題が発生します。

この関数は ではないことsynchronizedに注意してください。したがって、コピー中に元のリストが変更される可能性があるため、コピーを安全に返すことさえできないことに注意してください (参照の変更はアトミックupdate()であるため、メソッドでそれを行うのは安全です)。 .

次のように、同期されたメソッドからコピーを返すことができます。

public synchronized LinkedList<T> getEvents()
{
    return new LinkedList<T>(events);
}

しかし、それは不必要なコピーとロックをもたらします。それが重要かどうかは、防御コーディングまたはパフォーマンス要件を重視するかどうかによって異なります。パフォーマンス上の理由から、このようにしていると思います。

于 2013-03-28T17:30:45.993 に答える
0

これがあなたの問題です

  events = eventQueue;
  eventQueue.clear()

割り当てたら、を介してパブリックへevents = eventQueueの参照をエスケープしていますeventQueue

public LinkedList<T> getEvents()
{
    return events;
}

getEvents()1 つのスレッドが実際にあるキューを反復処理し、eventQueue別のスレッドが呼び出しaddEventている可能性があります。 synchronizedin addEvent がイテレータと一致しなくgetEvents()なるため、コモディティが取得されます。

私の提案は、本当にイベントを公開したい場合は、新しいコレクションで行うことです。

  events = new LinkedList<T>(eventQueue);
  eventQueue.clear()
于 2013-03-28T17:35:23.007 に答える
0

で参照を配布するなど、のすべての使用を保護しない場合は、 を試す必要があります。eventQueuegetEvents()ConcurrentLinkedList

于 2013-03-28T17:36:26.690 に答える