0

n 個のスレッドが a を生成しBlockingQueueます。キューがいっぱいになると、コンシューマーはキューを空にして何らかの処理を行います。

次の 2 つの実装の選択肢からどのように決定すればよいですか?

選択肢 A : コンシューマーは定期的にキューをポーリングして、キューがいっぱいかどうか、すべてのライターが待機しているかどうかを確認します (結局のところ、これはブロッキング キューです : )。

選択肢 B : 同期された "put" メソッドを使用して独自のキューを実装します。提供された要素を配置する前に、キューがほぼ満杯でないかどうかをテストします (満杯から 1 要素を差し引いた値)。次に、要素を配置し、消費者に通知します (待機していました)。

最初の解決策は最も簡単ですが、ポーリングを行います。それは私を悩ませます。私の意見では、2 番目の解決策はエラーが発生しやすく、より多くのコーディングが必要になります。

4

5 に答える 5

2

Exchanger インスタンスとともにキュー インスタンスを内部的にラップするプロキシ キューを作成することをお勧めします。プロキシ メソッドは呼び出しを内部キューに委任します。追加時に内部キューが満杯かどうかを確認し、満杯の場合は内部キューをコンシューマ スレッドと交換します。コンシューマー スレッドは、満杯のキューと引き換えに空のキューを交換します。プロキシ キューは空のキューを埋め続けますが、消費者はいっぱいになったキューを処理し続けることができます。両方のアクティビティを並行して実行できます。両当事者の準備ができたら、再び交換できます。

class MyQueue implements BlockingQueue{
    Queue internalQueue = ...
    Exchanger<Queue> exchanger;

    MyQueue(Exchanger<BlockingQueue> ex){
    this.exchanger = ex;
    }

     .
     .
     .

    boolean add (E e) {
      try{
        internalQueue.add(e);
      }catch(IllegalStateException ise){
        internalQueue = exchanger.exchange(internalQueue);
      }
      internalQueue.add(e);     
    }

}

class Consumer implements Runnable {
    public void run() {
        Queue currentQueue = new empty queue;
        while (...){
           Object o = currentQueue.remove();
           if (o == null){
              currentQueue = exchanger.exchange(currentQueue);
              continue;
           }
           //cast and process the element
        } 
    }
}
于 2012-05-15T11:53:58.640 に答える
0

オブザーバーパターンを使用します。コンシューマーにキュー通知機能を登録してもらいます。プロデューサーがプットを行うと、キューはリスナーに通知するかどうかを決定します。

于 2012-05-15T11:17:02.013 に答える
0

2番目の解決策は明らかに優れています。そして、それはそれほど複雑ではありません。他のものを継承またはラップしてBlockingQueue、そのメソッドを次のようにオーバーライドできますoffer()。「実際の」offer()を呼び出します。が返された場合はtrue、終了します。それ以外の場合は、作業スレッドをトリガーして動作させ、すぐoffer()にタイムアウトで呼び出します。

これがほとんど擬似コードです:

public boolean offer(E e) {
    if (queue.offer(e)) {
        return true;
    }
    boolean result = queue.offer(e, timeout, unit); // e.g. 20 sec. - enough for worker to dequeue at least one task from the queue, so the place will be available.
    worker.doYouJob();
    return result; }
于 2012-05-15T10:40:00.237 に答える
0

必要なキューの実装があるかどうかはわかりません。消費者は、キューがいっぱいになるまで待機し、完全に排出されて処理が開始されたときにのみ待機します。

キューがいっぱいになるまで、消費者に対してキューをブロックする必要があります。キューがいっぱいになるまで待機させるには、drain() メソッドをオーバーライドする必要があると考えてください。消費者よりも、drain メソッドを呼び出して待つだけです。生産者から消費者への通知は必要ありません。

于 2012-05-15T11:10:27.663 に答える
0

シンプルでうまく機能するCountdownLatchを使用しました。他のアイデアをありがとう:)

于 2012-05-16T08:10:22.713 に答える