web-dev-qa-db-ja.com

ArrayBlockingQueueよりLinkedBlockingQueueを優先する場合

LinkedBlockingQueueよりArrayBlockingQueueを優先する場合

LinkedBlockingQueueArrayBlockingQueueの間で使用するデータ構造は次の場合です。

  1. 効率的な読み取りと書き込みが必要な場合
  2. メモリのフットプリントを小さくする必要があります

同様の質問がありますが、どちらが優先されるべきかという事実を強調していませんか?

リンク:

37
Vaibhav Gupta

Boris the Spiderは、すでにArrayBlockingQueueLinkedBlockingQueueの最も顕著な違いを概説しています-前者は常に境界があり、後者は境界がありません。

したがって、無制限のブロッキングキューが必要な場合、LinkedBlockingQueueとして使用されるLinkedTransferQueueまたはBlockingQueueJava.util.concurrentツールボックスからの最善策です。

しかし、制限されたブロッキングキューが必要だとしましょう。最終的には、実際のワークロードのシミュレーションを使用した広範な実験に基づいて実装を選択する必要があります。それにも関わらず、ここでは、選択や実験結果の解釈に役立ついくつかの注意事項を示します。

  • ArrayBlockingQueueは、構成可能な(オン/オフ)スケジューリング公平性ポリシーを使用して作成できます。これは、公平性が必要な場合、または生産者/消費者の飢starを回避したい場合に最適ですが、スループットが犠牲になります。
  • ArrayBlockingQueueはそのバッキング配列を事前に割り当てます。そのため、使用中にノードを割り当てませんが、メモリのかなりの部分になる可能性のあるものをすぐに使用します。
  • ArrayBlockingQueueはパフォーマンスのばらつきが少ないはずです。全体的に可動部分が少なく、よりシンプルで洗練されていないシングルロックアルゴリズムを使用し、使用中にノードを作成せず、キャッシュ動作はかなり一貫している必要があります。
  • LinkedBlockingQueueは、ヘッドとテールに別々のロックを使用するため、スループットが向上するはずです。
  • LinkedBlockingQueueはノードを事前に割り当てません。これは、メモリフットプリントがサイズとほぼ一致することを意味しますが、ノードの割り当てと解放のための作業が発生することも意味します。
  • LinkedBlockingQueueはおそらくキャッシュの動作が悪くなり、それ自体のパフォーマンスに影響する可能性がありますが、誤った共有により他のコンポーネントのパフォーマンスにも影響する可能性があります。

ユースケースとパフォーマンスをどの程度重視するかに応じて、Java.util.concurrentの外側を見て、 Disruptor (非常に高速ですが、ある程度特殊な有界ノンブロッキングを検討することもできます。リングバッファー)または JCTools (プロデューサーとコンシューマーの数に応じて保証が異なるさまざまな境界付きまたは境界なしのキュー)。

51

JavaDoc for ArrayBlockingQueue から

bounded配列に裏打ちされたブロッキングキュー。

重点鉱山

LinkedBlockingQueueのJavaDoc から:

リンクされたノードに基づくoptionally-boundedブロッキングキュー。

重点鉱山

したがって、boundedキューが必要な場合は、unboundedキューLinkedBlockingQueueを使用する必要があります。

boundedキューの場合、より良い結果を得るためにベンチマークする必要があります。

11