java监听器详解-java如何监听http请求
一、 CopyOnWriteArrayList介绍
它相当于线程安全的ArrayList。和ArrayList一样,它是个可变数组;但是和ArrayList不同的时,它具有以下特性:
二、 CopyOnWriteArrayList原理三、 CopyOnWriteArrayList 属性介绍
public class CopyOnWriteArrayList
implements List, RandomAccess, Cloneable, java.io.Serializable {
private static final long serialVersionUID = 8673264195747942595L;
/**
* 监视器锁
*/
final transient Object lock = new Object();
/** 一个缓存数组,使用volatile修饰。 */
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;
}
}
四、 构造器
//无参构造,默认创建的是一个长度为0的数组
public CopyOnWriteArrayList() {
setArray(new Object[0]);
}
//参数为Collection的构造方法
public CopyOnWriteArrayList(Collection extends E> c) {
Object[] es;
//判断传递的是否就是一个CopyOnWriteArrayList集合
if (c.getClass() == CopyOnWriteArrayList.class)
//如果是,直接调用getArray方法,获得传入集合的array然后赋值给elements
es = ((CopyOnWriteArrayList>)c).getArray();
else {
//先将传入的集合转变为数组形式
es = c.toArray();
//c.toArray()可能不会正确地返回一个 Object[]数组,那么使用Arrays.copyOf()方法
if (c.getClass() != java.util.ArrayList.class)
es = Arrays.copyOf(es, es.length, Object[].class);
}
//直接调用setArray方法设置array属性
setArray(es);
}
//创建一个包含给定数组副本的list
public CopyOnWriteArrayList(E[] toCopyIn) {
setArray(Arrays.copyOf(toCopyIn, toCopyIn.length, Object[].class));
}
说明:
上面介绍的是CopyOnWriteList的初始化,三个构造方法都比较易懂
五、添加add方法
public boolean add(E e) {
//加锁
synchronized (lock) {
//获得list底层的数组array
Object[] es = getArray();
//获得数组长度
int len = es.length;
//拷贝到新数组,新数组长度为len+1
es = Arrays.copyOf(es, len + 1);
//给新数组末尾元素赋值
es[len] = e;
//用新的数组替换掉原来的数组
setArray(es);
return true;
}
}
六、获取元素 get(int index)
使用get(i)可以获取指定位置i的元素,当然如果元素不存在就会抛出数组越界异常。
public E get(int index) {
return elementAt(getArray(), index);
}
static E elementAt(Object[] a, int index) {
return (E) a[index];
}
六、remove(int index)
public E remove(int index) {
//加锁
synchronized (lock) {
//获取原数组
Object[] es = getArray();
//获取原数组长度
int len = es.length;
//获取原数组index处的值
E oldValue = elementAt(es, index);
//因为数组删除元素需要移动,所以这里就是计算需要移动的个数
int numMoved = len - index - 1;
Object[] newElements;
if (numMoved == 0)
//计算的numMoved=0,表示要删除的是最后一个元素
//那么旧直接将原数组的前len-1个复制到新数组中,替换旧数组即可
newElements = Arrays.copyOf(es, len - 1);
//要删除的不是最后一个元素
else {
//创建一个长度为len-1的数组
newElements = new Object[len - 1];
//将原数组中index之前的元素复制到新数组
System.arraycopy(es, 0, newElements, 0, index);
//将原数组中index之后的元素复制到新数组
System.arraycopy(es, index + 1, newElements, index,
numMoved);
}
//用新数组替换原数组
setArray(newElements);
return oldValue;
}
}
remove(int index)的作用就是将”volatile数组“中第index个元素删除。它的实现方式是,如果被删除的是最后一个元素,则直接通过Arrays.copyOf()进行处理,而不需要新建数组。否则,新建数组,然后将”volatile数组中被删除元素之外的其它元素“拷贝到新数组中;最后,将新数组赋值给”volatile数组“。和add(E e)一样,remove(int index)也是”在操作之前,获取独占锁;操作完成之后,释放独占是“;并且”在操作完成时,会通过将数据更新到volatile数组中“。
七、修改元素
修改也是属于写 ,所以需要获取lock,下面就是set方法的实现
public E set(int index, E element) {
//加锁
synchronized (lock) {
//获取数组array
Object[] es = getArray();
//获取index位置的元素
E oldValue = elementAt(es, index);
// 要修改的值和原值不相等
if (oldValue != element) {
//克隆一个新数组
es = es.clone();
//替换元素
es[index] = element;
}
// Ensure volatile write semantics even when oldvalue == element
// 即使在oldvalue==元素的情况下也要确保易失性写入语义
setArray(es);
return oldValue;
}
}
八、 迭代器
public Iterator iterator() {
return new COWIterator(getArray(), 0);
}
static final class COWIterator implements ListIterator {
/** Snapshot of the array */
//array的快照版本
private final Object[] snapshot;
/** Index of element to be returned by subsequent call to next. */
//后续调用next返回的元素索引(数组下标)
private int cursor;
//构造器
COWIterator(Object[] es, int initialCursor) {
cursor = initialCursor;
snapshot = es;
}
//变量是否结束:下标小于数组长度
public boolean hasNext() {
return cursor < snapshot.length;
}
//是否有前驱元素
public boolean hasPrevious() {
return cursor > 0;
}
//获取元素
//hasNext()返回true,直接通过cursor记录的下标获取值
//hasNext()返回false,抛出异常
@SuppressWarnings("unchecked")
public E next() {
if (! hasNext())
throw new NoSuchElementException();
return (E) snapshot[cursor++];
}
@SuppressWarnings("unchecked")
public E previous() {
if (! hasPrevious())
throw new NoSuchElementException();
return (E) snapshot[--cursor];
}
public int nextIndex() {
return cursor;
}
public int previousIndex() {
return cursor - 1;
}
/**
* Not supported. Always throws UnsupportedOperationException.
* @throws UnsupportedOperationException always; {@code remove}
* is not supported by this iterator.
*/
public void remove() {
throw new UnsupportedOperationException();
}
/**
* Not supported. Always throws UnsupportedOperationException.
* @throws UnsupportedOperationException always; {@code set}
* is not supported by this iterator.
*/
public void set(E e) {
throw new UnsupportedOperationException();
}
/**
* Not supported. Always throws UnsupportedOperationException.
* @throws UnsupportedOperationException always; {@code add}
* is not supported by this iterator.
*/
public void add(E e) {
throw new UnsupportedOperationException();
}
@Override
public void forEachRemaining(Consumer super E> action) {
Objects.requireNonNull(action);
final int size = snapshot.length;
int i = cursor;
cursor = size;
for (; i < size; i++)
action.accept(elementAt(snapshot, i));
}
}
说明:COWIterator不支持修改元素的操作。例如,对于remove(),set(),add()等操作java监听器详解,COWIterator都会抛出异常!
另外java监听器详解,需要提到的一点是,CopyOnWriteArrayList返回迭代器不会抛出ConcurrentModificationException异常,即它不是fail-fast机制的!
参考: