私は次のケースを持っています、
public class Test {
private static final int MAX_NUMBER = 10_00_00;
public static void main(String[] args) {
List<Integer> list = new CopyOnWriteArrayList<>();
long start = System.nanoTime();
for(int i = 0; i < MAX_NUMBER; i++) {
list.add(i * 2);
}
long end = System.nanoTime();
System.out.println(((end - start) / Math.pow(10, 9)));
}
}
出力
6.861539857
これは、約 100 秒かかったのに比べて、かなりゆっくりと要素を追加します。ドキュメントで理由を知りましたが、ArrayList
0.004690843
ArrayList
基になる配列の新しいコピーを作成することによって、すべての変更操作 (追加、設定など) が実装されるのスレッドセーフなバリアント。
したがって、私の理解では、このリストに新しい要素を追加するたびに、新しい新しい配列が作成され、この配列の最後のインデックスに要素が追加されます。ロックインadd
メソッドを見つけましたが、それとは別に、そのメソッドは実際に毎回新しい配列を作成しています。
私が自分のプログラムを増やしMAX_NUMBER
たとき10_00_000
、プログラムは実行され続け、決して終了しません(そうなるでしょうが、私はそれほど長く待つことはできません)。
Collections.synchronizedList
速度でスレッドセーフが必要な場合は、より良い選択だと思います。私はそれを使用し、それは約かかりました0.007673728
。
私の質問:
- 内部的に新しい配列を作成するのはなぜスレッドセーフがこれに関連しているのでしょうか?
- の場合、なぜそんなに時間がかかったの
MAX_NUMBER = 10_00_000
ですか?( で約6秒かかったようにMAX_NUMBER = 10_00_00
)これは、ミュータティブ操作が毎回新しい配列を作成するために発生していますか? CopyOnWriteArrayList
これは、膨大な数の要素があり、他のものを選択した方がよい場合にパフォーマンスが低下することを意味しますか (つまりCollections.synchronizedList
)?CopyOnWriteArrayList
これが、パブリック API で通常見られない理由ですか? これ以外に欠点はありますか?