私はBlockingQueueの概念に不慣れで、wait()とnotify()の必要性がなくなったという印象を受けました。スレッド同期の予備テストとして次のコードを作成しました(わかりやすくするために一部のコードは省略しています)。
q = new LinkedBlockingQueue<flight>();
generator = new EventGenerator(q,flight);
southwest = new Airline(q);
new Thread(generator).start();
new Thread(southwest).start();
プロデューサークラスEventGeneratorを使用します。EventGeneratorは、初期状態(SC)からすべての状態を通過して、ゲートAGに到達するまで飛行します。
import java.util.concurrent.BlockingQueue;
public class EventGenerator implements Runnable
{
private final BlockingQueue<flight> bqueue;
private final flight f;
EventGenerator(BlockingQueue<flight> q, flight f1)
{
bqueue = q;
f = f1;
}
public void run()
{
try
{
while (f.state != "AG") { bqueue.put(produce()); }
}
catch (InterruptedException ex)
{
System.out.println(ex);
System.exit(0);
}
}
flight produce()
{
if (f.state.equals("SC")){ f.state = "BD"; }
else if (f.state.equals("BD")) { f.state = "LG"; }
else if (f.state.equals("LG")) { f.state = "TO"; }
else if (f.state.equals("TO")) { f.state = "LD"; }
else if (f.state.equals("LD")) { f.state = "AG"; }
return f;
}
消費者クラスの航空会社は、フライトの状態の各変更を受け取り、それを印刷します。
import java.util.concurrent.BlockingQueue;
public class Airline implements Runnable
{
private final BlockingQueue<flight> bqueue;
Airline(BlockingQueue<flight> q)
{
bqueue = q;
}
public void run()
{
try
{
while (!bqueue.isEmpty()) { consume(bqueue.take());}
}
catch (InterruptedException ex)
{
System.out.println(ex);
System.exit(0);
}
}
void consume(flight f)
{
System.out.println("Flight no. " + f.flightno + " is now in state " + f.state);
}
}
プロジェクトはコンパイルされ、エラーなしで実行されます。しかし、私は結果が次のようなものになることを期待していました(そして望んでいます)。
Flight no. 1 is now in state SC
Flight no. 1 is now in state BD
Flight no. 1 is now in state LG
Flight no. 1 is now in state TO
Flight no. 1 is now in state LD
Flight no. 1 is now in state AG
しかし、代わりに、私はほとんど常に次のようになります。
Flight no. 1 is now in state AG
Flight no. 1 is now in state AG
Flight no. 1 is now in state AG
Flight no. 1 is now in state AG
Flight no. 1 is now in state AG
BlockingQueueを正しく実装していませんか?