0

Prod-Cons の問題に対する単純な Blocking Queue の例を書きました。以下の例は機能しません。エンキュー/デキューロジックの追加/削除部分を待機中のスレッドの通知と交換しない限り。BlockingQueue のどの実装でも、この動作の明確な説明を見つけることができませんでした。エンキューの部分は、要素を追加してから通知するのが正しいのではないでしょうか? このようにして、コンシューマー スレッドが実行されるときに、コンシューマーへの要素があり、null を返さないことを保証できます。説明してください。

import java.util.LinkedList;
import java.util.Queue;

public class BlockingQueueCustom<T> {

    private int size = 10;
    private Queue<T> queue = new LinkedList<T>();

    public BlockingQueueCustom(int s) {
        this.size = s;
    }

    public synchronized void enqueue(T element) throws InterruptedException {
        while (queue.size() == size) {
            wait();
        }
        queue.add(element); //Comment this part to make it work
        if (queue.size() == 0) {
            this.notifyAll();
        }
        //queue.add(element); Uncommenting this will make it work
    }

    public synchronized T dequeue() throws InterruptedException {
        while (queue.size() == 0) {
            this.wait();
        }
        T element = queue.remove(); //Comment this part to make it work
        if (queue.size() == size) {
            this.notifyAll();
        }
            return element; //Comment this part to make it work
        //return queue.remove(); Uncommenting this will make it work
    }
} 
4

1 に答える 1

8

エンキューの部分は、要素を追加してから通知するのが正しいのではないでしょうか?

同期されたメソッドにいるため、その部分は実際には問題ではありませんenqueue。とにかくメソッドを離れるまで、他のスレッドは実行されません。ただし、のテストに関してsize()重要です。ここを見て:

if (queue.size() == 0)

要素を追加したばかりの場合、どのようにそれが真実であると期待できますか? 代わりに 1 であることを確認できます。つまり、要素を追加するは 0 である必要があります。または、別の変数を保持することもできます。

boolean shouldNotify = queue.size() == 0;
queue.add(element);
if (shouldNotify) {
    this.notifyAll();
}
于 2013-09-16T05:51:44.683 に答える