Java での同時キューの実装
この記事では、Java での同時実行キューの最も効果的な実装のいくつかと、どの実装を利用する必要があるかについて説明します。
Java の同時キュー
まず、3つのキューすべてについて説明します。
Java ConcurrentLinkedQueue
ConcurrentLinkedQueue
にはロック機能は組み込まれていません。 この直接的な結果として、add と poll の両方がスレッドセーフであり、すぐに戻ることが保証されている、待機のない手法が提供されます。
クライアントが永久ループで待機することになった場合、どのオプションを選択しても、最良の代替手段としてブロッキング キューを選択する必要があります。 さらに、他のスレッドをブロックせずにウェイトフリー方式を使用することもできます。
このキューのロックではなく、CAS または Compare-And-Swap が使用されています。 これらのシステムではブロッキング データ構造の使用が許可されておらず、この方法を使用することで多くのメリットが得られるため、これは最新のリアクティブ システムにとって優れた選択肢です。
Java ArrayBlockingQueue
内部的に、このキューは配列を使用します。 その結果、サイズが事前に決定された制限付きキューが作成されます。
ArrayBlockingQueue
の put
操作と take
操作は同じロックを共有します。 パフォーマンス ヒットは、エントリが上書きされないことを保証する価値があります。
具体的には、キューは、配列が使用される前に配列を事前に割り当てます。 これは全体的に増加する可能性がありますが、メモリの使用量が多すぎる可能性もあります。
そのような用途の 1つに、単純なタスク キューがあります。 このような状況で少人数のお客様を完成させるために、多くのスタッフを揃えるのが一般的です。
このキューのサイズには上限があるため、メモリの制約がある場合にバッファ ゾーンを提供します。 一例として、大容量のキューが空のままになる期間が長くなる可能性があります。
公平性ポリシーとは、ロックの実装がスレッドの順序を合理的に維持することを意味します。 スレッド A が最初にロック取得フェーズに入り、スレッド B が入ると、スレッド A がロックを取得します。
正義がなければ、結果は不明確です。 次のスレッド以降に予定されている可能性があります。
Java LinkedBlockingQueue
LinkedBlockingQueue
内の各アイテムは、キューによって使用される LinkedList バリエーション内の新しいノードによって表されます。
LinkedBlockingQueue
のパフォーマンスは、実行ごとに大きく異なります。 つまり、 最も適切なデータ構造を使用していることを保証するために、常に状況をプロファイリングする必要があります。
Java で実装するのに最適なキュー
アイテムがキューに追加またはキューから削除されるたびに、LinkedBlockingQueue
はノードの割り当てと割り当て解除を実行する必要があります。 したがって、キューが急速に増減する場合は、ArrayBlockingQueue
が適しています。
ArrayBlockingQueue
のサイズは常に同じです。 容量が 10 の 11 番目のアイテムを追加すると、既存のスレッドがアイテムを削除するまで insert
ステートメントが停止します。
多くのスレッドが同時にキューに項目を追加および削除しようとすると (キューが使用できない場合)、公平性の問題が発生します。 公平性メカニズムのおかげで、何かを要求した最初のスレッドが常に最初に取得されます。
これがないと、あるスレッドの待機時間が別のスレッドの待機時間よりも大幅に長くなり、予期しない動作が発生する可能性があります。 ただし、公平性を管理する負担により、スループットが低下します。
ただし、選択は、ブロッキングが必要かどうかによって異なります。 供給者はたくさんいるのに、買い手は 1 人だけという状況のように聞こえます。
多くのコンシューマーがあり、プロデューサーが 1つしかない場合、ブロッキング動作は必要ない場合があります。 このような場合、コンシューマーはキューが空かどうかを確認し、空であれば処理を続行できます。
Java での ArrayBlockingQueue
の実装
ArrayBlockingQueue
の実装は、single-lock
二重条件技術を利用しています。 そのコンストラクタ 1 には、基礎となるデータ構造、Array および LinkedList がそれぞれあります。
以下は、ArrayBlockingQueue
のコンストラクタです。
public ArrayBlockingQueue(int capacity, boolean fair) {
if (capacity < = 0)
throw new IllegalArgumentException();
this.items = new Object[capacity];
lock = new ReentrantLock(fair);
notEmpty = lock.newCondition();
notFull = lock.newCondition();
}
I have been working as a Flutter app developer for a year now. Firebase and SQLite have been crucial in the development of my android apps. I have experience with C#, Windows Form Based C#, C, Java, PHP on WampServer, and HTML/CSS on MYSQL, and I have authored articles on their theory and issue solving. I'm a senior in an undergraduate program for a bachelor's degree in Information Technology.
LinkedIn