当前位置: 主页 > JAVA语言

java监听器详解-java如何监听http请求

发布时间:2023-04-03 09:10   浏览次数:次   作者:佚名

一、 CopyOnWriteArrayList介绍

它相当于线程安全的ArrayList。和ArrayList一样,它是个可变数组;但是和ArrayList不同的时,它具有以下特性:

java监听器详解_java如何监听http请求_java监听特定异常

二、 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;
    }
}

四、 构造器

java监听特定异常_java如何监听http请求_java监听器详解

//无参构造,默认创建的是一个长度为0的数组
public CopyOnWriteArrayList() {
    setArray(new Object[0]);
}

//参数为Collection的构造方法
public CopyOnWriteArrayList(Collection 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));
}

说明:

java监听器详解_java监听特定异常_java如何监听http请求

上面介绍的是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)

java如何监听http请求_java监听特定异常_java监听器详解

使用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;
    }
}

java如何监听http请求_java监听特定异常_java监听器详解

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;
    }
}

java监听器详解_java监听特定异常_java如何监听http请求

八、 迭代器

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 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机制的!

参考: