ブロッキングキューとトランスファーキューの違い
-
26-10-2019 - |
質問
JSR166YおよびJava 7のBlockingQueue/LinkedBlockingQueueと新しいTransferqueue/LinkedTransferqueueタイプの違いについて少し混乱しています
解決
生産者が消費者が要素を受け取るのを待つことができるブロッキングキュー。たとえば、メッセージの合格アプリケーションでは、プロデューサーが時々(メソッド転送(e)を使用して)消費者がテイクや投票を呼び出している要素の受領を待つことがありますが、領収書を待つことなく(メソッドプットを介して)要素を呼び出すことがあります。
言い換えれば、BlockingQueueを使用する場合、要素をキューにするだけです(キューがいっぱいの場合はブロックされます)。トランスファーキューを使用すると、他のスレッドが要素を受信するまでブロックすることもできます(新しい使用する必要があります transfer
そのための方法)。これが違いです。 BlockingQueueを使用すると、他のスレッドが要素を削除するまで待つことはできません(Synchronousqueueを使用する場合にのみ、実際にはキューではありません)。
これ以外に、Transferqueueもブロッキングキューです。 Transferqueueで利用可能な新しい方法をご覧ください。 http://download.oracle.com/javase/7/docs/api/java/util/concurrent/transferqueue.html (Transfer、TryTransfer、HasWaitingConsumer、GetWaitingConsumercount)。
Java SE 7のコレクションフレームワークの拡張機能 明示的に言う:
インターフェイストランスファーが追加されました。これは、生産者が消費者が要素を受け取るのを待つことができるBlockingQueueインターフェイスの改良です。新しいインターフェイスの1つの実装は、このリリースLinkedTransferqueueにも含まれています。
他のヒント
ずっと前の質問と @Peterの答えは本当に詳細です。トランスファーが実際にどのように機能するかを知りたい人のために、以下のライブデモを参照できるかもしれません。
import java.util.concurrent.LinkedTransferQueue;
import java.util.concurrent.TransferQueue;
public class TransferQueueExample {
TransferQueue<String> queue = new LinkedTransferQueue<String>();
class Producer implements Runnable{
@Override
public void run() {
// TODO Auto-generated method stub
for(int i = 0; i < 2; i++){
try{
System.out.println("Producer waiting to transfer: " + i);
queue.transfer("" + i);
System.out.println("Producer transfered: " + i);
}catch(Exception e){
e.printStackTrace();
}
}
}
}
class Consumer implements Runnable{
@Override
public void run() {
// TODO Auto-generated method stub
for(int i = 0; i < 2; i++){
try{
Thread.sleep(2000);
System.out.println("Consumer waiting to comsume: " + i);
queue.take();
System.out.println("Consumer consumed: " + i);
}catch(Exception e){
e.printStackTrace();
}
}
}
}
public static void main(String args[]){
TransferQueueExample example = new TransferQueueExample();
new Thread(example.new Producer()).start();
new Thread(example.new Consumer()).start();
}
}
出力は次のとおりです。
Producer waiting to transfer: 0
Consumer waiting to comsume: 0
Consumer consumed: 0
Producer transfered: 0
Producer waiting to transfer: 1
Consumer waiting to comsume: 1
Consumer consumed: 1
Producer transfered: 1
transfer
違いが発生する場所です。
要素を消費者に転送し、必要に応じて待っています。
より正確には、既にそれを受け取るのを待っている消費者が存在する場合(テイクまたはタイミングの投票で)指定された要素をすぐに転送します。
Javadocとして、 transfer
消費者が製品を奪うまで待ちます。
それが理由です "Producer waiting to transfer: 0"
最初に、約2秒後に呼ばれ、消費者が受け取った後、 Producer transfered: 0
その後、呼ばれます。
要するに、BlockingQueueは、プロデューサーによって作成された要素がキューにある必要があることを保証しますが、トランスファーはさらに一歩進んで、一部の消費者によって要素が「消費」されたことを保証します。
何らかの形のパフォーマンスの違いがあるようですが。見る arrayblockingqueue vs linkedtransferqueue and Friends