CopyOnWriteArrayList<E>
来源:互联网 发布:億展网络怎么样 编辑:程序博客网 时间:2024/06/05 12:05
CopyOnWriteArrayList简介
CopyOnWriteArrayList,即“写入时复制”容器,在每次修改(add、remove)时都会创建新的底层基础数组,然后在新数组上修改,最后将新数组作为容器的基础数组。因此,非修改操作不需要加锁,修改操作时才加锁,并发性能较同步List好。
CopyOnWriteArrayList实现
以下定义了基础数组及数组操作
public class CopyOnWriteArrayList<E> implements List<E>, RandomAccess, Cloneable, java.io.Serializable { private static final long serialVersionUID = 8673264195747942595L; /** The lock protecting all mutators */ transient final ReentrantLock lock = new ReentrantLock(); /** The array, accessed only via getArray/setArray. */ private volatile transient 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; } /** * Creates an empty list. */ public CopyOnWriteArrayList() { setArray(new Object[0]); } /** * Creates a list containing the elements of the specified * collection, in the order they are returned by the collection's * iterator. * * @param c the collection of initially held elements * @throws NullPointerException if the specified collection is null */ public CopyOnWriteArrayList(Collection<? extends E> c) {Object[] 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); }
非修改操作:
// Positional Access Operations /** * {@inheritDoc} * * @throws IndexOutOfBoundsException {@inheritDoc} */ public E get(int index) { return (E)(getArray()[index]); }
修改操作:
/** * Replaces the element at the specified position in this list with the * specified element. * * @throws IndexOutOfBoundsException {@inheritDoc} */ public E set(int index, E element) {final ReentrantLock lock = this.lock;lock.lock();try { Object[] elements = getArray(); Object oldValue = 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 semanticssetArray(elements); } return (E)oldValue;} finally { lock.unlock();} } /** * Appends the specified element to the end of this list. * * @param e element to be appended to this list * @return <tt>true</tt> (as specified by {@link Collection#add}) */ 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();} }
优点
1、较同步List有更好的并发性能
2、其迭代器不需要加锁,且不会抛出ConcurrentModificationException,这正是迭代器所期望的
缺点
1、每次修改容器时都会复制底层数组,需要一定开销,可能引起Minor GC或Full GC适用场景
仅当迭代操作远大于修改操作时,才应该使用“写入时复制”容器。一个典型的场景时“事件通知系统”,在分发通知时需要迭代已注册的监听列表,而注册和注销事件监听器的操作要远少于分发通知的操作.
public class VisualComponent {private final List<KeyListener> keyListeners= new CopyOnWriteArrayList<KeyListener>();private final List<MouseListener> mouseListeners= new CopyOnWriteArrayList<MouseListener>();public void addKeyListener(KeyListener listener) {keyListeners.add(listener);}public void addMouseListener(MouseListener listener) {mouseListeners.add(listener);}public void removeKeyListener(KeyListener listener) {keyListeners.remove(listener);}public void removeMouseListener(MouseListener listener) {mouseListeners.remove(listener);}}
阅读全文
0 0
- CopyOnWriteArrayList<E>
- CopyOnWriteArraySet<E>和CopyOnWriteArrayList<E>
- CopyOnWriteArrayList
- CopyOnWriteArrayList
- CopyOnWriteArrayList
- CopyOnWriteArrayList
- CopyOnWriteArrayList
- CopyOnWriteArrayList
- CopyOnWriteArrayList
- CopyOnWriteArrayList
- CopyOnWriteArrayList
- CopyOnWriteArrayList
- CopyOnWriteArrayList
- CopyOnWriteArrayList
- CopyOnWriteArrayList
- CopyOnWriteArrayList
- CopyOnWriteArrayList
- CopyOnWriteArrayList
- c++强制转型
- R语言数据结构介绍-入门篇
- 基础DP学习之【货币问题】
- javascript逻辑运算符“||”和“&&”
- 欢迎使用CSDN-markdown编辑器
- CopyOnWriteArrayList<E>
- 基于OpenCV批量处理文件夹中的图片的方法
- jquery入门
- 一个屌丝程序猿的人生(十五)
- 输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5
- php微信域名检测实例
- java集合框架之Set和Map之间的关系
- COCOS2D学习第一天
- JavaScript