简单说一下java中线程安全的List
一、Vector
Vector是大家熟知的线程安全的List集合,不过他的性能是最差,所有的方法都是加了synchronized来同步,从而保证线程安全。
源码也是使用数组来存储数据,有以下构造方法。
/ * Constructs an empty vector with the specified initial capacity and * capacity increment. * * @param initialCapacity the initial capacity of the vector * @param capacityIncrement the amount by which the capacity is * increased when the vector overflows * @throws IllegalArgumentException if the specified initial capacity * is negative */ public Vector(int initialCapacity, int capacityIncrement) { super(); if (initialCapacity < 0) throw new IllegalArgumentException("Illegal Capacity: "+ initialCapacity); this.elementData = new Object[initialCapacity]; this.capacityIncrement = capacityIncrement; } / * Constructs an empty vector with the specified initial capacity and * with its capacity increment equal to zero. * * @param initialCapacity the initial capacity of the vector * @throws IllegalArgumentException if the specified initial capacity * is negative */ public Vector(int initialCapacity) { this(initialCapacity, 0); } / * Constructs an empty vector so that its internal data array * has size {@code 10} and its standard capacity increment is * zero. */ public Vector() { this(10); } / * Constructs a vector containing the elements of the specified * collection, in the order they are returned by the collection's * iterator. * * @param c the collection whose elements are to be placed into this * vector * @throws NullPointerException if the specified collection is null * @since 1.2 */ public Vector(Collection
c) { elementData = c.toArray(); elementCount = elementData.length; // c.toArray might (incorrectly) not return Object[] (see ) if (elementData.getClass() != Object[].class) elementData = Arrays.copyOf(elementData, elementCount, Object[].class); }
它的增加、修改、获取、删除等都通过synchronized来同步。
public synchronized void insertElementAt(E obj, int index) { modCount++; if (index > elementCount) { throw new ArrayIndexOutOfBoundsException(index + " > " + elementCount); } ensureCapacityHelper(elementCount + 1); System.arraycopy(elementData, index, elementData, index + 1, elementCount - index); elementData[index] = obj; elementCount++; } public synchronized void addElement(E obj) { modCount++; ensureCapacityHelper(elementCount + 1); elementData[elementCount++] = obj; } public synchronized boolean removeElement(Object obj) { modCount++; int i = indexOf(obj); if (i >= 0) { removeElementAt(i); return true; } return false; } public synchronized void removeAllElements() { modCount++; // Let gc do its work for (int i = 0; i < elementCount; i++) elementData[i] = null; elementCount = 0; } public synchronized E get(int index) { if (index >= elementCount) throw new ArrayIndexOutOfBoundsException(index); return elementData(index); } public synchronized E set(int index, E element) { if (index >= elementCount) throw new ArrayIndexOutOfBoundsException(index); E oldValue = elementData(index); elementData[index] = element; return oldValue; } public synchronized boolean add(E e) { modCount++; ensureCapacityHelper(elementCount + 1); elementData[elementCount++] = e; return true; }
二、Collections.SynchronizedList
SynchronizedList是Collections类的静态内部类,它能把所有 List 接口的实现类转换成线程安全的List,比 Vector 有更好的扩展性和兼容性。
SynchronizedList的构造方法如下:
SynchronizedList(List
list) { super(list); this.list = list; } SynchronizedList(List
list, Object mutex) { super(list, mutex); this.list = list; }
SynchronizedList的部分方法源码如下:
public boolean equals(Object o) { if (this == o) return true; synchronized (mutex) {return list.equals(o);} } public int hashCode() { synchronized (mutex) {return list.hashCode();} } public E get(int index) { synchronized (mutex) {return list.get(index);} } public E set(int index, E element) { synchronized (mutex) {return list.set(index, element);} } public void add(int index, E element) { synchronized (mutex) {list.add(index, element);} } public E remove(int index) { synchronized (mutex) {return list.remove(index);} } public int indexOf(Object o) { synchronized (mutex) {return list.indexOf(o);} } public int lastIndexOf(Object o) { synchronized (mutex) {return list.lastIndexOf(o);} } public boolean addAll(int index, Collection
c) { synchronized (mutex) {return list.addAll(index, c);} } public ListIterator
listIterator() { return list.listIterator(); // Must be manually synched by user } public ListIterator
listIterator(int index) { return list.listIterator(index); // Must be manually synched by user } public List
subList(int fromIndex, int toIndex) { synchronized (mutex) { return new SynchronizedList<>(list.subList(fromIndex, toIndex), mutex); } } @Override public void replaceAll(UnaryOperator
operator) { synchronized (mutex) {list.replaceAll(operator);} } @Override public void sort(Comparator
c) { synchronized (mutex) {list.sort(c);} } / * SynchronizedRandomAccessList instances are serialized as * SynchronizedList instances to allow them to be deserialized * in pre-1.4 JREs (which do not have SynchronizedRandomAccessList). * This method inverts the transformation. As a beneficial * side-effect, it also grafts the RandomAccess marker onto * SynchronizedList instances that were serialized in pre-1.4 JREs. * * Note: Unfortunately, SynchronizedRandomAccessList instances * serialized in 1.4.1 and deserialized in 1.4 will become * SynchronizedList instances, as this method was missing in 1.4. */ private Object readResolve() { return (list instanceof RandomAccess ? new SynchronizedRandomAccessList<>(list) : this); }
它所有方法都是带同步对象锁的,和 Vector 一样,它不是性能最优的。
三、CopyOnWriteArrayList
CopyOnWriteArrayList是java1.5以后才加入的新类,从命名可以理解为复制在写入的List。
它的添加时加锁的(ReentrantLock ,非synchronized同步锁),读操作是没有加锁。
添加和删除方法部分代码实现:
public boolean add(E e) { final ReentrantLock lock = this.lock; lock.lock(); try { Object[] elements = getArray(); int len = elements.length; Object[] newElements = Arrays.copyOf(elements, len + 1); newElements[len] = e; setArray(newElements); return true; } finally { lock.unlock(); } } private boolean remove(Object o, Object[] snapshot, int index) { final ReentrantLock lock = this.lock; lock.lock(); try { Object[] current = getArray(); int len = current.length; if (snapshot != current) findIndex: { int prefix = Math.min(index, len); for (int i = 0; i < prefix; i++) { if (current[i] != snapshot[i] && eq(o, current[i])) { index = i; break findIndex; } } if (index >= len) return false; if (current[index] == o) break findIndex; index = indexOf(o, current, index, len); if (index < 0) return false; } Object[] newElements = new Object[len - 1]; System.arraycopy(current, 0, newElements, 0, index); System.arraycopy(current, index + 1, newElements, index, len - index - 1); setArray(newElements); return true; } finally { lock.unlock(); } }
添加或者删除元素时,先加锁,再进行复制替换操作,最后再释放锁。
它的优势在于,读操作是不加任和锁。这样做的好处是,在高并发情况下,读取元素时就不用加锁,写数据时才加锁,大大提升了读取性能。
看下它的 get 方法源码:
private E get(Object[] a, int index) { return (E) a[index]; } / * {@inheritDoc} * * @throws IndexOutOfBoundsException {@inheritDoc} */ public E get(int index) { return get(getArray(), index); }
发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/224958.html原文链接:https://javaforall.net
