Javaのいくつかのブロッキングキュー
JavaのBlockingQueue
インターフェースは、スレッドセーフなアクセスキューであり、プロデューサーおよびコンシューマーアプリケーションのシナリオに適しており、次の2つの追加操作をサポートします。
- プロデューサースレッドは、キューがいっぱいになるまでデータをブロッキングキューに入れ続けます。キューがいっぱいになると、プロデューサースレッドはブロックし、コンシューマースレッドがデータをフェッチするのを待ちます。
- コンシューマスレッドは、キューが空になるまで、ブロッキングキューからデータをフェッチし続けます。キューが空になると、コンシューマースレッドはプロデューサースレッドがデータを配置するのを待機するのをブロックします。
BlockingQueueインターフェース
BlockingQueue
4つの異なる処理方法を提供します。
例外をスローする | 特別な値を返す | ブロックし続ける | タイムアウト終了 | |
---|---|---|---|---|
挿入方法 | add(o) | オファー(o) | put(o) | オファー(o、タイムアウト、時間単位) |
除去方法 | remove(o) | poll() | take(o) | poll(o、timeout、timeunit) |
検査方法 | 素子() | ピーク() | — | — |
- 例外をスローします:
- 追加:データを挿入するときに、ブロッキングキューがいっぱいの場合、例外
IllegalStateException
がスローされます。それ以外の場合、挿入は正常に返されtrue
ます。容量制限キューを使用してキューをブロックする場合は、このoffer
方法を使用することをお勧めします。IllegalStateException
-容量制限のため、現時点で要素を追加できない場合ClassCastException
-指定された要素のクラスにより、この要素がこのキューに追加されない場合NullPointerException
-指定された要素がnullの場合IllegalArgumentException
-指定された要素の一部のプロパティにより、この要素がこのキューに追加されない場合
- remove:データを削除するときに、このデータがキューにある場合、削除は正常
true
に返されfalse
ます。それ以外の場合は返されます。1つ以上のオブジェクトが含まれている場合は、1つだけ削除して、を返しtrue
ます。注意:それはremove(o)
あるBlockingQueue
方法remove()
のQueue
インターフェース、それはある方法のインターフェース。 - 要素:キューが空の場合、例外がスローされ
NoSuchElementException
ます。キューが空でない場合、キュークエリの先頭はデータを返しますが、データは削除しません。これはremove()
、element
同じQueue
インターフェイスの方法とは異なります。
- 追加:データを挿入するときに、ブロッキングキューがいっぱいの場合、例外
- 特別な値を返します:
- オファー:データを挿入するときに、ブロッキングキューがいっぱいでない場合、挿入は成功して
true
戻りfalse
ます。それ以外の場合は返されます。制限付き(容量制限キュー)ブロッキングキューを使用するoffer
場合は、例外をスローするadd
メソッドではなく、メソッドを使用することをお勧めします。 - ポーリング:このメソッドは
Queue
インターフェースです。キューが空でない場合は、キューのhead要素をクエリして削除し、返します。キューが空の場合は、を返しnull
ます。 - peek:このメソッドは
Queue
インターフェースです。キューが空の場合は、を返します。null
これは異なりpoll
ます。キューが空でない場合、クエリはキューの先頭にあるデータを返しますが、データは削除しませんremove()
。これは異なります。
- オファー:データを挿入するときに、ブロッキングキューがいっぱいでない場合、挿入は成功して
- 常にブロックされています:
- put:データを挿入するときに、キューがいっぱいの場合はブロッキング待機キューが使用可能であり、待機期間中に中断された場合はスローされ
InterruptedException
ます。 - take:キューのhead要素を照会、削除、および返します。キューが空の場合は、ブロックしている待機キューを使用できます。待機期間中に中断された場合は、をスローし
InterruptedException
ます。
- put:データを挿入するときに、キューがいっぱいの場合はブロッキング待機キューが使用可能であり、待機期間中に中断された場合はスローされ
- タイムアウト後に終了:
- オファー:データを挿入するときに、キューがいっぱいの場合は、キューが使用可能になるまで指定された時間をブロックし、待機期間中に中断された場合は、をスローし
InterruptedException
ます。挿入が成功した場合はを返しtrue
、指定した時間後もキューがまだ使用できない場合はを返しfalse
ます。 - poll:キューのhead要素を照会、削除、および返します。キューが空の場合、指定された時間ブロックし、キューが使用可能になるのを待ちます。待機期間中に中断された場合は、スローされ
InterruptedException
ます。削除が成功した場合は、キューの先頭要素を返しnull
ます。指定した時間が経過してもキューがまだ使用できない場合は、を返します。
- オファー:データを挿入するときに、キューがいっぱいの場合は、キューが使用可能になるまで指定された時間をブロックし、待機期間中に中断された場合は、をスローし
Queue
nullをキューに挿入することはできませんNullPointerException
。そうしないと、nullがスローされます。
Javaでキューをブロックする
JDK7は7つのブロッキングキューを提供します。それぞれ
- ArrayBlockingQueue:配列構造体で構成される制限付きブロッキングキュー。
- LinkedBlockingQueue:リンクリスト構造で構成される制限付きブロッキングキュー。
- PriorityBlockingQueue:優先度の並べ替えをサポートする無制限のブロッキングキュー。
- DelayQueue:優先キューを使用して実装された無制限のブロッキングキュー。
- SynchronousQueue:要素を格納しないブロッキングキュー。
- LinkedTransferQueue:リンクリスト構造で構成される無制限のブロッキングキュー。
- LinkedBlockingDeque:リンクリスト構造で構成される双方向のブロッキングキュー。
ArrayBlockingQueue
ArrayBlockingQueue
これは、アレイベースの先入れ先出し(FIFO)制限付きブロッキングキューです。
- キューを作成するときは、キューの容量(容量)、つまり配列のサイズを指定する必要があります。
- キューを作成するときに
Collection
、キュー要素を初期化するために渡すことができます。 - キューが作成されると、キューの容量を変更することはできません。
- キューはフェアモードとアンフェアモードをサポートし、デフォルトはアンフェアモードです。
- キューにはロックが1つだけあり、書き込みロックと読み取りロックは分離されておらず、同時実行制御は従来の2条件(
notEmpty
、notFull
)アルゴリズムを採用しています。
LinkedBlockingQueue
LinkedBlockingQueue
これは、リンクされたノードの先入れ先出し(FIFO)に基づくオプションで制限されたブロッキングキューです。
- キューを作成するときに、追加のオーバーヘッドを回避するために、キュー容量を指定できます。キュー容量を指定しない場合、デフォルトのキュー容量は
Integer.MAX_VALUE
です。 - キューを作成するときに
Collection
、キュー要素を初期化するために渡すことができます。現時点では、キュー容量を指定することはできません。デフォルトはInteger.MAX_VALUE
です。 - キューの
count
現在使用されているキュー要素の数AtomicInteger
を防止するput
とtake
の競争。 ArrayBlockingQueue
違いは、LinkedBlockingQueue
読み込みロックと書き込みロックが分離され、キューの中の2つのロックがあること。- 使用時に
LinkedBlockingQueue
、キューサイズがデフォルト値であり、本番速度が消費速度よりも速い場合、メモリオーバーフローが発生する可能性があります。 LinkedBlockingQueue
理論的にArrayBlockingQueue
はスループットが高くなりますが、ほとんどの実際のアプリケーションシナリオでは、パフォーマンスが向上しません。
PriorityBlockingQueue
PriorityBlockingQueue
これは、優先度をサポートする配列ベースの無制限のブロッキングキューです。このキューのデータ構造はヒープです。
- キューを作成するときに、初期容量(initialCapacity)を指定すると、デフォルトの初期容量
DEFAULT_INITIAL_CAPACITY
は11になります。 - キューを作成するときに、キューの容量(容量)ではなく、キューの初期容量(initialCapacity)を指定できます。
PriorityBlockingQueue
LinkedBlockingQueue
オプションの制限付き(オプションで制限付き)に対する無制限(無制限)、無制限とは、キューの作成時にキューの最大容量を指定できないことを意味します。制限がないことPriorityBlockingQueue
ではありません。LinkedBlockingQueue
デフォルト(指定できる、であるこれはデフォルトの容量を示すことに注意してください、Integer.MAX_VALUE
値よりも大きいが)最大容量はありInteger.MAX_VALUE
、かつPriorityBlockingQueue
最大容量ですMAX_ARRAY_SIZE=Integer.MAX_VALUE-8
。PriorityBlockingQueue
無制限のもう1つの意味は、キューが無制限であり、フルキャパシティーなどがないため、キューがいっぱいであるためにプロデューサースレッドがブロックされないことです。offer(E e, long timeout, TimeUnit unit)
最後の2つのパラメーターは効果がありません。ソースコードを見ると、メソッドの実装が直接呼び出されていることがわかりoffer(e)
ます。ただし、キューが空の場合take
でも、ブロックされます。offer(e)
決して戻らない、戻らないfalse
、またはブロックしoffer(E e, long timeout, TimeUnit unit)
ないfalse
。PriorityBlockingQueue
キューは配列を介して実装されます。元の配列がいっぱいになると、配列をコピーしてキューの容量が拡張されます。新しく拡張された配列の容量がを超えるMAX_ARRAY_SIZE
とOutOfMemoryError
、例外がスローされます。- デフォルトでは、要素は自然な順序で配置され、要素の並べ替え規則はコンパレータによって指定することもできます。要素は昇順で配置されます。
DelayQueue
DelayQueue
これはPriorityQueue
、要素の遅延取得をサポートするブロッキングキューの実装に基づいています。
DelayQueue
に格納されるオブジェクトは、Delayed
インターフェイスを実装する必要があります。- 何満了要素が存在しない場合、何も存在しない
head
、およびpoll
メソッド戻りヌルは。 - 要素の
getDelay(TimeUnit.NANOSECONDS)
戻り値が0以下になると、要素は期限切れになります。 - 有効期限が切れていない要素を使用
take
およびpoll
削除することはできませんが、これらの有効期限が切れていない要素は、有効期限が切れた要素と同じように扱われます。たとえばsize
、メソッドによって返される数量は、期限切れの要素と期限切れの要素の合計です。
DelayQueue
該当するシナリオ:
- アイドル状態のリンクを閉じます。サーバーには多くのアイドルリンクがあり、一定期間後にそれらを閉じます。
- 期限切れのキャッシュを削除します。一定期間後、キャッシュされたオブジェクトをいくつか削除します。
- タスクタイムアウト処理。ネットワークプロトコルスライディングウィンドウ要求応答の相互作用で、タイムアウトの応答しない要求を処理します。
- 注文が生成されてから60秒後、SMS通知がユーザーに送信されます。
- 注文から15分後、ユーザーが支払いを行わない場合、注文はクローズされます。
上記のいくつかのシーンの例を通して、それが特定の期間の後に特定のビジネス処理DelayQueue
を行うのに適していることがわかります。
SynchronousQueue
SynchronousQueue
データバッファはありませんBlockingQueue
。
- 1つのスレッドの挿入は、別のスレッドの削除操作が完了するのを待つ必要があり、その逆も同様です。
SynchronousQueue
ハンドオフ設計、つまり、あるスレッドで実行されているオブジェクトが特定の情報、タスク、またはイベントを別のスレッドで実行されているオブジェクトに渡す必要があるシナリオに適しています。SynchronousQueue
公正および不公正なモデルをサポートします。peek
要素は削除しようとしたときにのみ存在するため、同期キューでは実行できません。- 反復に使用できる要素がないため、キューを反復できません。
Executors.newCachedThreadPool()
SynchronousQueue
キューはで使用されます。
LinkedTransferQueue
LinkedTransferQueue
これは、リンクされたノードに基づく無制限のブロッキングキューです。
- 無制限キュー(
Integer.MAX_VALUE
)、入力および出力キューはFIFO(先入れ先出し)の原則を採用しています。 - プロデューサーは、キューに追加された要素が特定のコンシューマーによって消費されるまでブロックします。これは主にスレッド間のメッセージの送信に使用されます。これ
SynchronousQueue
は非常に似ていSynchronousQueue
ますが、それよりも優れています。 LinkedTransferQueue
このメソッドを使用して通常の要素追加操作を実行するかBlockingQueue
、このput
メソッドを使用してtransfer
追加をブロックすることができます。SynchronousQueue
柔軟性と比較して、キューの長さはゼロではなく、ブロック挿入と非ブロック挿入の要素が共存できます。- 現在、エレメントの受信を待機しているコンシューマーが存在する場合(コンシューマーが
take()
メソッドまたは時間制限のあるメソッドを使用する場合poll()
)、transfer
メソッドはプロデューサーから渡されたエレメントをコンシューマーにすぐに転送できます。要素の受信を待機しているコンシューマーがない場合、transfer
メソッドは要素をキューのtail
ノードに格納し、要素がコンシューマーによって消費されるまで待機してから戻ります。
LinkedBlockingDeque
LinkedBlockingDueue
これは、リンクされたノードに基づくオプションで制限された双方向ブロッキングキューです。
- ブロッキングキューは、FIFOとFILOの両方の操作モード、つまり、キューの先頭と末尾からの同時操作(挿入/削除)をサポートします。
- ブロッキングキューはスレッドセーフです。
- LinkedBlockingDequeを初期化するときに、その過度の拡張を防ぐために容量を設定できます。
- 双方向ブロッキングキューは、「ワークスティーリング」(ワークスティーリング)モードで使用できます。