概要
java.util.concurrent
パッケージに含まれるクラスであり、スレッドセーフ1なコレクションである。
特徴
このリストは、他のスレッドが要素を変更しても、読み取り操作を行うスレッドには影響を与えない。要素の追加、削除、および更新が必要な場合、新しいコピーが作成され、変更が行われる。
このため、読み取りと書き出しを同時に行なっても、ConcurrentModificationException
が発生することはない。
例
import java.util.concurrent.CopyOnWriteArrayList;
public class CopyOnWriteArrayListExample {
public static void main(String[] args) {
CopyOnWriteArrayList<String> list = new CopyOnWriteArrayList<>();
// 要素の追加
list.add("Apple");
list.add("Banana");
list.add("Orange");
// 要素の反復処理
for (String fruit : list) {
System.out.println(fruit);
}
// 別のスレッドで要素を変更する場合
new Thread(() -> {
list.add("Mango");
list.remove("Apple");
}).start();
// 要素の反復処理(変更されていない状態で行われる)
for (String fruit : list) {
System.out.println(fruit);
}
}
}
この例では、CopyOnWriteArrayList
を使用してリストを作成し、要素を追加する。
その後、別のスレッドで要素が変更され、新しい要素が追加され、既存の要素が削除される。
最後に、リストの内容を再び反復処理して表示する。
実行結果
Apple
Banana
Orange
Apple
Banana
Orange
Mango
Banana
Orange
最初の反復処理では、リストの初期状態であるApple
、Banana
、Orange
が表示される。
その後、別のスレッドで要素が変更されるが、変更前のリストの状態であるApple
、Banana
、Orange
が最後の反復処理で表示される。
CopyOnWriteArrayList
は要素の追加や削除が発生するたびに新しいコピーが作成されるため、メモリ使用量が増える。
また、要素の変更が頻繁に行われる場合にはパフォーマンスが低下する可能性があるため、使用ケースに応じて適切に検討する必要がある。
-
正しく排他制御され、複数のスレッドから同時に利用されても競合やデッドロックなどが起こらないこと。 ↩