したがって、次のオブジェクトがあります(例のために簡略化されています)。
public class SomeListener implements EventListener{
public final Object lock = new Object();
public int receivedVal;
@Override
public onDataAvailable(int val){
synchronized(lock){
System.out.println("listener received val: " + val);
receivedVal = val;
lock.notifyAll();
}
}
}
そして、私はこのコードをメインスレッドのどこかに持っています(ここでも簡略化されています):
SomeListener listener = new SomeListener();
EventGenerator generatorThread = new EventGenerator();
generatorThread.addListener(listener);
synchronize(listener.lock){
generatorThread.start();
listener.lock.wait();
System.out.println("value is: " + listener.receivedVal);
}
//some other stuff here....
ここで、EventGeneratorオブジェクトはval = 1で「onDataAvailable」を呼び出し、次に別のスレッドでval=2を呼び出します。基本的に、私が期待するのは次のとおりです。
listener received val: 1
value is: 1
listener received val: 2
ただし、通常は次のようになります。
listener received val: 1
listener received val: 2
value is: 2
これは、「onDataAvailable」の2番目の呼び出しが、メインスレッドが起動する前にロックを取得するかのようです。期待される結果を得るには、単純なprintlnまたは「onDataAvailable」の同期ブロック後の短いスリープで十分ですが、それは醜いパッチのようです。
私はここで何が間違っているのですか?
リスナーを呼び出すスレッドを制御できないことに注意してください。これは基本的に、ネットワークを介してイベントを受信するスレッドです。同じメッセージで複数のイベントを受信することがあるため、「onDataAvailable」を次々に複数回呼び出すことがあり、これが問題につながります。また、2つの異なるメッセージで2つのイベントを受信する場合もあります。これにより、メインスレッドがイベント間でウェイクアップするのに十分な時間が残ります。