2

プロデューサースレッドとコンシューマースレッドの間で共有バッファーを作成するつもりでした。これが私のコードです:

class PQueue
{
    Token token;
    boolean flag = false;   // false: add, true: poll

    PQueue()
    {
        token = null;
    }

    synchronized void add(Token token)
    {
        if(flag == true)
        {
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        flag = true;
        notify();
        this.token = token;
    }

    synchronized Token poll()
    {
        if(flag == false)
        {
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        flag = false;
        notify();
        return this.token;
    }
}

私はマルチスレッドに不慣れです。潜在的な同時実行バグはありますか?これは、この目標を達成するための「標準/一般的な」方法ですか?それとも、もっと簡単で効率的な方法はありますか?

4

2 に答える 2

3

java.util.concurrentパッケージ、特にBlockingQueueそれを実装するインターフェースとクラスを見てください。これらは、あるスレッドから別のスレッドにメッセージを渡すためのものです。これSynchronousQueueはまさにあなたが実装しようとしているものです。

独自の実装にはいくつかの欠陥があります。1つは、両方の共有変数を宣言volatileして、一方のスレッドでの変更がもう一方のスレッドで確実に認識されるようにする必要があります。また、実際に呼び出されていないときに誤ってウェイクアップする可能性があるためif (flag == false)if (flag == true)テストは実際にはwhileループである必要があります。wait()notify()

個別のフラグ変数を使用するのではなく、トークンをnullに設定して、オブジェクトがないことを示すことをお勧めします。そして、キャッチして印刷し、盲目的に続行するのではなく、InterruptedException両方のメソッドで例外が発生した場合にその例外をスローするようにすることをお勧めします。これらはブロッキングメソッドであり、ブロッキングメソッドが中断される可能性を処理するのは呼び出し元の責任です。

また、あなたのクラスが何であるかはわかりませんTokenが、キュー内の何も実際にはそのタイプに依存していません。ジェネリックを定義してから、トークンを渡す場合PQueue<T>に使用する方が理にかなっています。PQueue<Token>

于 2012-08-14T05:34:51.577 に答える
1

1.Packagethread-safeのクラスとインターフェースを使用してみてくださいjava.util.concurrent

2.BlockingQueue Interfaceと一緒に使用しArrayBlockingQueue Classます。

于 2012-08-14T05:36:11.597 に答える