2009-03-11 21 views
4

名前はありますが、私はそれが何であるかわからないので、Googleには難しいです。交換可能な作業キュー

私が探しているのは、キューのペア、プロデューサによって使用される「保留」キュー、および消費者が使用する「処理」キューであるJava並行性ユーティリティのものです。キューをアトミックにスワップします。この方法(1つのプロデューサスレッド、1つのコンシューマスレッド)で使用する場合、個々のキューはスレッドセーフである必要はなく、スレッドセーフである必要はありません。

私はこれまでどこかでこれを見てきたことは知っていますが、私はおそらくこのようなものを自分で作ることができます。

編集:私は私が探しているプリミティブはアトミックにスワップすることができ、原子参照のペアであると思います。 (。&私は自分自身をキューに追加することができます)


編集2: @Alex Miller氏は、それは私が考えていたが、覚えていなかったことだったかのしつこい質問に答えました。しかし、それはスレッドの壁であり、プロデューサーをブロックする必要がないので、私の問題は解決しません。

@ sfossinがキューへの参照を交換することについてのポイントは良いものです。私が望んでいたのは、消費者がキューからアイテムを取り出して処理し始めた瞬間、それらのキューアイテムはすべて完了しなければならず、プロデューサーはその後アイテムを追加できないということでした。プロデューサはもう一方のキューにアイテムを追加する必要があります。したがって、ペアになった/スワップされたアトミック参照のセットは機能しません。

(学校バスが2つあり、そのうちの1つは常に乗客を待っていて、もう1つはいつも他の場所に運んでいるのと同じようなものです。)一度ドライバーが離れると、別のバスに乗る必要があります既に残っているにも関わらず、プロデューサはバスにアクセスできますが、これは許可されていません)。

私は代わりに1台のConcurrentLinkedQueueを使用し、コンシューマがキューに追加するセンチネル値を使用します。これにより、1つだけではなく、複数のプロデューサが存在することが可能になります。消費者がキュー上のアイテムのバッチを処理するためには、コンシューマはキューに少なくとも1つのアイテムがあることを待ってから、キューに入れ、アイテムを削除します。その後、消費者はバッチ間で何をしなくても行います。それが私が望む行動です。

必ずしも保証されたノンブロッキングアプローチ(ロックまたは​​メソッドはオプションです)が必要なわけではありませんが、それを簡単に設計してアプリケーションに適用するのが簡単です。

+0

を追加した後、私は、LockedQueueを考えていましたあなたが描いているように使用することができます。プロデューサーはq(pq)を持ち、消費者はq(cq)、lq.put(pq)を持ちます。 < - lq.get(cq)を実行する準備ができました。 < - バスで。 :P so 3 q、交換中のみロックします。 – sfossen

答えて

2
+0

それはそれだった!ありがとう! –

0

説明したようなデュアルキューを持つデータ構造はありませんが、concurrent utilsには、キューを作るためにたくさんのキューがあります。

あなたが説明している問題は非常に一般的ですが、私も同様に見つけることが期待されます。多分Java 1.7で。

2

リーダライタのロックされたキューは、おそらく良い考えです。それ以外の場合は、ローカルキューにアトミックにコピーする必要がある場合は、

読者が読んだり削除したり書いたりしていた間に、参照を入れ替えた場合、同期の問題が発生します。

RWLockは、複数のコンシューマ/プロデューサを許可します。

RWLocksから離れる理由は何ですか?

ロックと同様に、ロックは飢餓を防ぐためにできるだけ短い時間保持する必要があります。

またはこのようなデータの交換に使用します。各スレッドがそれ自身のキューを保持している。消費者の呼び出しのget(と

class LockedQueue 
{ 
    private final List<Data> q = new ArrayList<Data>(); 
    private final Lock lock = new ReentrantLock(); 

    public void get(List<Data> consumerQ) { 
     if(lock.tryLock()) { try { consumerQ .addAll(q); q.clear(); } finally { lock.unlock(); }} 
    } 
    public Data put(List<Data> producerQ) { 
     if(lock.tryLock()) { try { return q.addAll(producerQ ); producerQ .clear(); } finally { lock.unlock(); }} 
    } 
    public void clear() { 
     lock.lock(); try { q.clear(); } finally { lock.unlock(); } 
    } 
} 

)、空の場合や、各ループの最後と消費者の呼び出しプットで、非常に多くのアイテムや、時間や...

関連する問題