Copy-on-write简称cow,是一种用于集合的并发访问,和安全的优化策略。
可以同时进行写入和读取,在这个过程中,过程不一定是一致的,但结果一定是一致的。
LinkedTransferQueue类的transfer()方法是Java中的内置函数,通常用于将元素传输到正在等待接收的线程中,如果没有线程等待,则它将等待直到线程尽快进入等待状态等待线程到达的元素将被转移到其中。
E transfer(E e, boolean timed, long nanos) {
QNode s = null; // constructed/reused as needed
boolean isData = (e != null);
for (;;) {//死循环和cpu有关,和吞吐量有关
QNode t = tail;//尾部节点
QNode h = head;//头部节点
if (t == null || h == null)
continue;
if (h == t || t.isData == isData) { //只有一个节点,
QNode tn = t.next;
if (t != tail) // inconsistent read
continue;
if (tn != null) { // lagging tail
advanceTail(t, tn);
continue;
}
if (timed && nanos <= 0) //超时
return null;
if (s == null)
s = new QNode(e, isData);//空节点的处理
if (!t.casNext(null, s)) // failed to link in
continue;
advanceTail(t, s); // swing tail and wait移动尾节点并且等待
Object x = awaitFulfill(s, e, timed, nanos);//awaitFulfill的作用是通过自旋、或者阻塞当前线程来等待节点被匹配。
if (x == s) { // wait was cancelled
clean(t, s);
return null;
}
if (!s.isOffList()) { // not already unlinked
advanceHead(t, s); // unlink if head
if (x != null) // and forget fields
s.item = s;
s.waiter = null;
}
return (x != null) ? (E)x : e;
} else {
CopyOnWriteArrayList(Collection<? extends E> c)
这个方法是一个构造函数,主要是针对参数类型的转换。可以得到一个按照Collection迭代器,包含Collection内容的列表。
public E set(int index, E element)
该方法主要实现针对特定位置,传入特定参数,将旧的值替换为指定值,返回值为旧的value值。
public boolean add(E e)
对该集合进行加元素操作,利用Arrays工具类将旧的数组赋值给新数组,并且返回给全局变量。
public void add(int index, E element)
在指定位置替换元素时,是将旧的数组切割成两份,赋值给新数组。
public E remove(int index)
void removeRange(int fromIndex, int toIndex)
public boolean removeAll(Collection<?> c)
public class CopyOnWriteArrayList<E>
implements List<E>, RandomAccess, Cloneable, java.io.Serializable {
final transient ReentrantLock lock = new ReentrantLock();
//“transient关键字的作用是:被transient修饰的变量不参与序列化和反序列化。当一个对象被序列化的时候,transient型变量的值不包括在序列化的表示中,然而非transient型的变量是被包括进去的
private transient volatile Object[] array;
/**
* Gets the array. Non-private so as to also be accessible
* from CopyOnWriteArraySet class.
*/
final Object[] getArray() {
return array;
}
/**
* Sets the array.
*/
final void setArray(Object[] a) {
array = a;
}
public CopyOnWriteArrayList(Collection<? extends E> c) {
Object[] elements;
if (c.getClass() == CopyOnWriteArrayList.class)
elements = ((CopyOnWriteArrayList<?>)c).getArray();
else {
elements = c.toArray();
// c.toArray might (incorrectly) not return Object[] (see 6260652)
if (elements.getClass() != Object[].class)
elements = Arrays.copyOf(elements, elements.length, Object[].class);
}
setArray(elements);
}
@SuppressWarnings("unchecked")
private E get(Object[] a, int index) {
return (E) a[index];
}
public E get(int index) {
return get(getArray(), index);
}
public E set(int index, E element) {
final ReentrantLock lock = this.lock;
lock.lock();
try {
Object[] elements = getArray();
E oldValue = get(elements, index);
if (oldValue != element) {
int len = elements.length;
Object[] newElements = Arrays.copyOf(elements, len);
newElements[index] = element;
setArray(newElements);
} else {
// Not quite a no-op; ensures volatile write semantics
setArray(elements);
}
return oldValue;