java.util.concurrentバッグのソースコードは読みます.08 Copy OnWriteArayListとCopyOnWriteAraySet
4366 ワード
CopyOWriteArayListとCopyOnWriteAraySetは、データ構造のタイプからも類似しており、配列で実現されるデータのセットを保存するデータ構造であり、違いは簡単にListとsetの違いである.そこでここではまずCopyOWriteArayListについて議論してからCopyOnWriteAraySetにします.
ここで注目しているのはCopyOWriteで、字面から分かりやすく、書き込み操作のたびにデータを格納する配列をコピーし、コピーを修正して元の配列を上書きします.このようなデータ構造が適用される場合は、必ず読み取り操作が圧倒的に多く(書き込み操作が少ない)、かつデータ量が少ない場合(例えばブラックリスト)である.
したがって、CopyOWriteArayListの実現を見るとよく分かります.きっとvolatileの配列があります.一つのロックは書き込み操作に使われます.
ここで注目しているのはCopyOWriteで、字面から分かりやすく、書き込み操作のたびにデータを格納する配列をコピーし、コピーを修正して元の配列を上書きします.このようなデータ構造が適用される場合は、必ず読み取り操作が圧倒的に多く(書き込み操作が少ない)、かつデータ量が少ない場合(例えばブラックリスト)である.
したがって、CopyOWriteArayListの実現を見るとよく分かります.きっとvolatileの配列があります.一つのロックは書き込み操作に使われます.
/** The lock protecting all mutators */
transient final ReentrantLock lock = new ReentrantLock();
/** The array, accessed only via getArray/setArray. */
private volatile transient Object[] array;
配列全体をArays.co pyOfでコピーし、部分的にはSystem.arraycopyを使用します.以下ではadd方法を例に挙げます. public void add(int index, E element) {
final ReentrantLock lock = this.lock;
lock.lock();
try {
Object[] elements = getArray();
int len = elements.length;
if (index > len || index < 0)
throw new IndexOutOfBoundsException("Index: "+index+
", Size: "+len);
Object[] newElements;
int numMoved = len - index;
if (numMoved == 0)
newElements = Arrays.copyOf(elements, len + 1);
else {
newElements = new Object[len + 1];
System.arraycopy(elements, 0, newElements, 0, index);
System.arraycopy(elements, index, newElements, index + 1,
numMoved);
}
newElements[index] = element;
setArray(newElements);
} finally {
lock.unlock();
}
}
最後に要素を追加すると、Arays.co pyOfを使用して配列全体を新規作成してコピーし、中間に挿入するとSystem.arraycopyを使用して2つのセグメントに分けてコピーし、要素を挿入することができます.setAray方法の役割は、元の配列をカバーすることであり、コードは以下の通りである. final void setArray(Object[] a) {
array = a;
}
CopyOWriteAraySetについて簡単に話します.実はCopy OnWriteAraySetはCopy OnWriteArayListの包装類です.private final CopyOnWriteArrayList<E> al;
違いは、Setが重複要素を許さないため、CopyOWriteAraySetのaddメソッドで呼び出したのはCopyOnWriteArayListのaddIfAbsent方法です. public boolean add(E e) {
return al.addIfAbsent(e);
}