0

私が抱えている問題は、単一の生産者、複数の消費者の問題のようなものです。消費者が「違う」ことを除いて、私はそれを取る前に新しいアイテムを「覗く」(誰のためにあるかをチェックする)方法が必要です。

問題は、実際には複数のクライアントスレッドにサービスを提供する単一のサーバースレッドです。クライアントが情報を要求し、サーバーがこのクライアントに応答する必要があります

どうやってやるの?可能性は次のようなループです。

while (true) {
    if (q.peek() ... check here ...) {
        // do something
    } else {
        Sleep(...); // prevent taking up too much CPU?
    }
}

しかし、理想的/正しくないようですか?

4

3 に答える 3

2

次の 2 つのオプションがあります。

オプション 1. アイテムを取り出して「実際の」消費者に委譲するキューの 1 つの消費者を用意します。これには多くの作業が必要になります。これは、主な消費者が「実際の」消費者のどれが忙しいかを知る必要があるためです。さらに、「実際の」コンシューマの 1 つが他のコンシューマよりも多くのリソースを使用する場合、メインのコンシューマがメッセージのハンドオフを待機している間、キューがブロックされる可能性があります。

より良い解決策は次のとおりです。

オプション 2. コンシューマーのタイプごとに 1 つのキューを使用します。プロデューサは、各メッセージ タイプが属するキューを判断し、正しいキューにドロップします。次に、各コンシューマーは、関心のあるキューからプルします。

于 2013-02-26T04:09:57.340 に答える
0

次の操作を1つのブロックで同期することにより、アトミックにする必要がある場合があります。

// Make sure queue is final. If not, use a final Object monitor.
synchronized(queue) {
    queue.peek
    queue.pool
}

これは、コンシューマスレッドがキューに適切なターゲットメッセージが含まれていることを検出した後(からBlockingQueue.peek)、メッセージを消費できるようにするためです(からBlockingQueue.pool

それでも、あなたのソリューションは理想的ではありません。、という名前の手法を実装していますがbusy pooling、これは多くのCPUリソースを浪費する可能性があります。を利用しませんBlockingQueue.poolBlockingQueue.poolデータが利用可能になるまで、コンシューマースレッドを待機段階にします。

を最大限に活用するにはBlockingQueue.pool、各コンシューマスレッドが独自のキューを保持する必要があります。pool忙しくすることなく電話をかけることができるようにpeek

于 2013-02-26T04:27:35.713 に答える
0

BlockingQueue をまったく使用しない方がよい場合があります。

public class Synchronizer {
    Object obj;

    synchronized void put(Object obj) throws InterruptedException {
        this.obj = obj;
        notifyAll();
        while(obj != null) {
            wait();
        }
    }

    synchronized Object take() throws InterruptedException {
        for(;;) {
            wait();
            if (obj instanceof MyObject) {
                notifyAll();
                Object tmp = obj;
                obj = null;
                return tmp;
            }
        }
    }
}

BlockingQueue から消費する Synchronzer のバージョンがあるかもしれませんが

于 2013-02-26T04:41:57.827 に答える