0

私は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を正しく実装していませんか?

4

2 に答える 2

2
while (f.state != "AG") { bqueue.put(produce()); }

while (!bqueue.isEmpty()) { consume(bqueue.take());}

私はあなたの両方のwhile条件が本当にあなたが望むものではないのではないかと思います:最初のものは.equals()文字列の比較に使用する必要があります。2つ目は、コンシューマーがプロデューサーの後に実行されることを前提としています(そして、コンシューマーはプロデューサーよりも遅いと想定しています)。そうしないと、コンシューマーはキューが空であることに気付き、ループ全体をスキップします。

于 2013-02-21T23:09:14.027 に答える
2

あなたが現在抱えている問題は、実際にはproduceメソッドにあります。同じオブジェクトの状態を変更し、それを複数回キューに配置しています。あなたがしたいのは、実際に変更されたコピーをキューに置くことです。オブジェクトが不変である場合、Flightこの問題は発生しません。

上記とは別に、この答えは、whileループの条件に関する問題についても正しいです。

于 2013-02-21T23:12:04.530 に答える