Javaで最高の同時実行リストを選択する[終了]


98

スレッドプールには固定数のスレッドがあります。これらのスレッドは、共有リストに対して頻繁に書き込みおよび読み取りを行う必要があります

では、java.util.concurrentこの場合、パッケージ内のどのデータ構造(リストであることが望ましい、モニターフリーである必要があります)が最適ですか?


5
コレクションで何をしたいかによります。私のブログ投稿を参照しください(.Netに関するものですが、概念は同じです)。を使用して正しいスレッドセーフコードを記述できない場合がありますList
SLaks

1
現在、CopyOnWriteArrayListを使用していますが、依然としてConcurrentModificationException例外が時々スローされます。
象嘉道

2
コレクションで何をしているのかについて、より多くの情報を含めてください。そうすれば、人々はよりよく答えることができます。そうでなければ、それは単なる推測です。
mattsh

2
ConcurrentModificationException同期の問題から来ないかもしれません。また、たとえば、コレクションから要素を削除しようとするコレクションに対するforループでも発生します。
toto2

1
私はそれがパッケージの一部ではないことを知っていますが、誰かが試しましたVectorか?
WesternGun、

回答:


96

あった方がいい List

唯一の List実装java.util.concurrentCopyOnWriteArrayListです。Travis Webbが言及しているように、同期リストのオプションもあります。

とはいえ、あなたはそれが必要Listですか?コンカレントQueuesとMapsにはさらに多くのオプションがあり(SetsからMapsを作成できます)、これらの構造は、共有データ構造で実行したい多くの種類のことに対して最も理にかなっている傾向があります。

キューの場合、非常に多くのオプションがあり、どのオプションがそれを使用する必要があるかによって異なります。


14
CopyOnWriteArrayList書き込みには非常にコストがかかる(ただし、読み取りにはコストがかかる)という欠点があります。大量の書き込みを実行している場合は、同期したリストまたはキューを使用する方がよいでしょう。
Peter Lawrey

67

次のように、Javaコレクションをスレッドセーフにすることができます。

List newList = Collections.synchronizedList(oldList);

または、まったく新しいスレッドセーフリストを作成するには:

List newList = Collections.synchronizedList(new ArrayList());

http://download.oracle.com/javase/6/docs/api/java/util/Collections.html#synchronizedList(java.util.List)


7
このため、java.util.concurrentにはリストの実装がありません -ええと、メソッドConcurrentHashMapがあっても存在しCollections.synchronizedMapます。
aioobe

7
のJavadocを読んでくださいConcurrentHashMap。同期の実装の詳細は異なります。でsynchronizedメソッドを使用すると、Collections基本的にはJavaモニターでクラスがラップされるだけです。ConcurrentHashMapより賢い並行処理機能を使用します。
Travis Webb

1
うん。それでも、それはあなたの最後の文を一種の無効なものにします。
aioobe

1
モニターを使用する場合、プログラムのパフォーマンスは本当に悪いです:-(
象嘉道

5
を追加するだけで、newListの反復はスレッドセーフではありません。!!
bluelurker 2017年

9

リストのサイズが固定されている場合は、AtomicReferenceArrayを使用できます。これにより、スロットに対してインデックス付きの更新を実行できます。必要に応じて、リストビューを作成できます。


6

Paul Martinの「実用的なロックフリーの二重リンクリスト」に基づいてDoug Leaが作成したConcurrentDoublyLinkedListを確認することをお勧めします。java.util.Listインターフェースは実装していませんが、リストで使用するほとんどのメソッドを提供しています。

javadocによると:

Deque(両端キュー)の同時リンクリスト実装。同時挿入、削除、およびアクセス操作は、複数のスレッドにわたって安全に実行されます。イテレータは一貫性弱く、イテレータの作成時またはそれ以降のある時点での両端キューの状態を反映する要素を返します。それらはConcurrentModificationExceptionをスローせ、他の操作と同時に進行する場合があります。


5

ConcurrentLinkedQueueロックフリーキューを使用します(新しいCAS命令に基づく)。


7
... Listインターフェースを実装していません。
aioobe

1
eSniff、List.set(int index, Object element)ConcurrentLinkedQueueで実装するにはどうしますか?
John Vint

4
ほとんどの- List固有のメソッドは、Queue(たとえば、特定のインデックスで追加/設定する)を使用して実装できないか、実装することはできますが効率的ではありません(インデックスから取得)。だからあなたは本当にそれを包むことはできないと思います。とは言っQueueても、OPがを必要とする理由を実際に説明していないため、aの提案は問題ないと思いますList
ColinD

1
@ColinDそれが私が求めていた答えです。CLQをリストに含めることができない理由はいくつかあります。私は同意しますが、キューインターフェイスを除外できません。
John Vint

1
most️注目すべき点:「ほとんどのコレクションとは異なり、サイズメソッドは一定時間の操作ではない
Behrang Saeedzadeh 2018年

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.