Java CopyOnWriteArrayList 分析

来源:互联网 发布:凡人网络购物系统 编辑:程序博客网 时间:2024/05/26 07:30

java.util.concurrent.CopyOnWriteArrayList 是一个线程安全的List。

部份源码:

package java.util.concurrentpublic class CopyOnWriteArrayList<E> implements List<E>, RandomAccess, Cloneable, Serializable {      private transient volatile Object[] elements;    /**     * Creates a new empty instance.     */    public CopyOnWriteArrayList() {        elements = EmptyArray.OBJECT;    }    /**     * Creates a new instance containing the elements of {@code collection}.     */    @SuppressWarnings("unchecked")    public CopyOnWriteArrayList(Collection<? extends E> collection) {        this((E[]) collection.toArray());    }    /**     * Creates a new instance containing the elements of {@code array}.     */    public CopyOnWriteArrayList(E[] array) {        this.elements = Arrays.copyOf(array, array.length, Object[].class);    }    @Override public Object clone() {        try {            CopyOnWriteArrayList result = (CopyOnWriteArrayList) super.clone();            result.elements = result.elements.clone();            return result;        } catch (CloneNotSupportedException e) {            throw new AssertionError(e);        }    }    @SuppressWarnings("unchecked")    public E get(int index) {        return (E) elements[index];    }     public Iterator<E> iterator() {        Object[] snapshot = elements;        return new CowIterator<E>(snapshot, 0, snapshot.length);    }    public ListIterator<E> listIterator(int index) {        Object[] snapshot = elements;        if (index < 0 || index > snapshot.length) {            throw new IndexOutOfBoundsException("index=" + index + ", length=" + snapshot.length);        }        CowIterator<E> result = new CowIterator<E>(snapshot, 0, snapshot.length);        result.index = index;        return result;    }    public synchronized boolean add(E e) {        Object[] newElements = new Object[elements.length + 1];        System.arraycopy(elements, 0, newElements, 0, elements.length);        newElements[elements.length] = e;        elements = newElements;        return true;    }    public synchronized void add(int index, E e) {        Object[] newElements = new Object[elements.length + 1];        System.arraycopy(elements, 0, newElements, 0, index);        newElements[index] = e;        System.arraycopy(elements, index, newElements, index + 1, elements.length - index);        elements = newElements;    }     @Override public synchronized void clear() {        elements = EmptyArray.OBJECT;    }    public synchronized E remove(int index) {        @SuppressWarnings("unchecked")        E removed = (E) elements[index];        removeRange(index, index + 1);        return removed;    }    public synchronized E set(int index, E e) {        Object[] newElements = elements.clone();        @SuppressWarnings("unchecked")        E result = (E) newElements[index];        newElements[index] = e;        elements = newElements;        return result;    }    static int lastIndexOf(Object o, Object[] data, int from, int to) {        if (o == null) {            for (int i = to - 1; i >= from; i--) {                if (data[i] == null) {                    return i;                }            }        } else {            for (int i = to - 1; i >= from; i--) {                if (o.equals(data[i])) {                    return i;                }            }        }        return -1;    }    final Object[] getArray() {        // CopyOnWriteArraySet needs this.        return elements;    }    /**     * Iterates an immutable snapshot of the list.     */    static class CowIterator<E> implements ListIterator<E> {        private final Object[] snapshot;        private final int from;        private final int to;        private int index = 0;        CowIterator(Object[] snapshot, int from, int to) {            this.snapshot = snapshot;            this.from = from;            this.to = to;            this.index = from;        }        public void add(E object) {            throw new UnsupportedOperationException();        }        public boolean hasNext() {            return index < to;        }        public boolean hasPrevious() {            return index > from;        }        @SuppressWarnings("unchecked")        public E next() {            if (index < to) {                return (E) snapshot[index++];            } else {                throw new NoSuchElementException();            }        }        public int nextIndex() {            return index;        }        @SuppressWarnings("unchecked")        public E previous() {            if (index > from) {                return (E) snapshot[--index];            } else {                throw new NoSuchElementException();            }        }        public int previousIndex() {            return index - 1;        }        public void remove() {            throw new UnsupportedOperationException();        }        public void set(E object) {            throw new UnsupportedOperationException();        }    }    private void writeObject(ObjectOutputStream out) throws IOException {        Object[] snapshot = elements;        out.defaultWriteObject();        out.writeInt(snapshot.length);        for (Object o : snapshot) {            out.writeObject(o);        }    }    private synchronized void readObject(ObjectInputStream in)            throws IOException, ClassNotFoundException {        in.defaultReadObject();        Object[] snapshot = new Object[in.readInt()];        for (int i = 0; i < snapshot.length; i++) {            snapshot[i] = in.readObject();        }        elements = snapshot;    }}

内部维护了一个volatile Object[] elements,volatile修饰,表示即使在多线程环境中对它进行修改,每个线程都会实时拿到最新值

add()时,会调用System.arrayCopy(),copy出一个新的array,再赋值给elements。要保证该系列的操作原子性,所以在方法上加了synchronized

可以看到 add、remove、set这些修改性的操作都有synchronized锁。加了这个锁,即表示这些修改操作的Context开销会比较大


内部有一个CowIterator的迭代器。其内关于迭代的next()、previous(),都没有加锁。

因为这些方法内部操作的是一个不可变的对象:final Object[] snapshot。且构造方法中需要传入一个对象数组以完成final snapshot的初始化。

所以不论其他线程如何改变elements,已初始化的迭代器,都将不受影响

所以迭代操作的内存开销较小。

因此,如果需要一个迭代操作较多、修改操作较少的线程安全的List,可以考虑使用CopyOnWriteArrayList



0 0
原创粉丝点击