java.util.concurrentバッグのソースコードは読みます.08 Copy OnWriteArayListとCopyOnWriteAraySet

4366 ワード

CopyOWriteArayListとCopyOnWriteAraySetは、データ構造のタイプからも類似しており、配列で実現されるデータのセットを保存するデータ構造であり、違いは簡単にListとsetの違いである.そこでここではまずCopyOWriteArayListについて議論してからCopyOnWriteAraySetにします.
ここで注目しているのは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);

    }