次のような状況があります。
- 拡張することしかできないデータ構造 (私は末尾にのみ追加します)
- すでに見た要素を追跡できるようにする必要があります (インデックスがあり、理想的には、この特定の要素からリストを再度トラバースできるようにしたい)
- 読み取りがブロックされないようにし、新しい要素を追加して、キュー全体ではなくキューの末尾のみをロックしたいと思います
これは、複数のスレッドによって大幅に変更される構造です。
これに最適なデータ構造は何でしょうか?
配列リスト。これは、インデックスを使用して最後に表示された要素に直接アクセスできるのが理想的ですが、同時変更の例外が発生します。私はそれを同期させることができましたが、ロックを避けたいです(または、新しい要素を追加するために同時書き込みが発生する可能性がある唯一の要素であるため、最後の要素以外のロックは避けたいです)
ConcurrentLinkedQueue。これで同時実行性の問題は解決しますが、整数インデックスではなく反復の現在の位置を保存する必要があるという問題があります。これには、反復子が作成されてからリストに追加された新しいオブジェクトを返すことが保証されていない、一貫性の低い反復子を返すという問題があります (ソース: javadoc)。
インデックスをキーとするConcurrentHashMap 。これには、正しいインデックスに対応するデータに直接アクセスできるという利点がありますが、要素をインデックスからインデックス + 1 などに効率的にトラバースできる「getNext」演算子がないという問題があります。
ベクトルこれは、同時変更例外をスローせず、直接アクセスを許可するものを許可するという私の問題のほとんどを解決します。ただし、すべてのメソッドが同期されているため、アレイリストに比べてパフォーマンスが低下します。構造を拡張したいだけで、途中にレコードを挿入したくないことを考えると、読み取りもパフォーマンスに影響を与えるこの重いソリューションに行くのは気が進まない (一方、私のユースケースを考えると、要素のインデックス実際には変更されないため、テールではない読み取りを同期する必要はありません)
カスタムデータ構造:保存したいオブジェクトの配列と、この配列の末尾(最後の要素セット)へのポインターを保持し、新しいオブジェクトを挿入するときに、末尾と末尾が指すオブジェクトをロックします。オブジェクトが現在のサイズを超えると、サイズ変更操作がロックされます。
最善の戦略/他のより効率的な実装は何ですか?