CopyOnWriteArrayList<E>

本文详细介绍了CopyOnWriteArrayList的工作原理及其应用场景。该容器通过在每次修改时复制底层数组来实现高并发读取,适合读多写少的场景。文章还探讨了其迭代器实现,以及使用时需要注意的问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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 semantics
		setArray(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,这正是迭代器所期望的。原因在于其内部迭代器实现COWIterator<E>自己持有了一个底层基础数组snapshot,在构造时传入,snapshot指向外部类CopyOnWriteArrayList的Object[] array;但CopyOnWriteArrayList有数据修改时将采取复制并创建 newArray,并将array指向newArray,但这并不影响snapshot指向原array。因此,迭代器不需要考虑与CopyOnWriteArrayList之间加锁,且迭代器实现为不允许修改数据,因此迭代器本身也不需要加锁。是一个非常好的设计。
 

缺点

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

}

}
package com.example.kucun2.entity.data; import android.os.Handler; import android.os.Looper; import android.util.Log; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.concurrent.CopyOnWriteArrayList; public class SynchronizedList<T extends SynchronizableEntity> { private static final String TAG = "AsyncEntityList"; private final List<T> internalList = new CopyOnWriteArrayList<>(); private final List<ListChangeListener<T>> listeners = new ArrayList<>(); private final EntityChangeListener<T> entityChangeListener = new EntityChangeListener<>(); private Class<T> type; // 列表变更监听器接口 public interface ListChangeListener<T> { void onItemAdded(T item, int position); void onItemRemoved(T item, int position); void onSyncStarted(T item); void onSyncSuccess(T item); void onSyncFailure(T item, String error); void onListChanged(); } public Class<T> getType() { return type; } public SynchronizedList(Class<T> type) { this.type=type; } // 操作回调接口 public interface OperationCallback<T> { void onSuccess(T item); void onFailure(T item, String error); } // 注册监听器 public void addListChangeListener(ListChangeListener<T> listener) { listeners.add(listener); } // 移除监听器 public void removeListChangeListener(ListChangeListener<T> listener) { listeners.remove(listener); } // 通知所有监听器 private void notifyListeners(Runnable action) { new Handler(Looper.getMainLooper()).post(() -> { for (ListChangeListener<T> listener : listeners) { action.run(); } }); } // 异步添加元素 public void addAsync(T item, OperationCallback<T> callback) { if (item == null || internalList.contains(item)) return; // 1. 预添加状态(UI可立即显示) int position = internalList.size(); internalList.add(item); registerListener(item); notifyListeners(() -> { for (ListChangeListener<T> listener : listeners) { listener.onItemAdded(item, position); listener.onSyncStarted(item); } }); // 2. 后台执行同步 new Thread(() -> { item.sync("add", new SynchronizableEntity.SyncCallback() { @Override public void onSyncSuccess(SynchronizableEntity entity) { notifyListeners(() -> { for (ListChangeListener<T> listener : listeners) { listener.onSyncSuccess((T) entity); listener.onListChanged(); } }); if (callback != null) callback.onSuccess((T) entity); } @Override public void onSyncFailure(String error) { internalList.remove(item); unregisterListener(item); notifyListeners(() -> { for (ListChangeListener<T> listener : listeners) { listener.onSyncFailure((T) item, error); listener.onItemRemoved((T) item, position); } }); if (callback != null) callback.onFailure((T) item, error); } }); }).start(); } // 异步移除元素 public void removeAsync(T item, OperationCallback<T> callback) { if (!internalList.contains(item)) return; int position = internalList.indexOf(item); internalList.remove(item); unregisterListener(item); notifyListeners(() -> { for (ListChangeListener<T> listener : listeners) { listener.onItemRemoved(item, position); listener.onSyncStarted(item); } }); new Thread(() -> { item.sync("remove", new SynchronizableEntity.SyncCallback() { @Override public void onSyncSuccess(SynchronizableEntity entity) { notifyListeners(() -> { for (ListChangeListener<T> listener : listeners) { listener.onSyncSuccess((T) entity); } }); if (callback != null) callback.onSuccess((T) entity); } @Override public void onSyncFailure(String error) { internalList.add(position, item); // 回滚 registerListener(item); notifyListeners(() -> { for (ListChangeListener<T> listener : listeners) { listener.onSyncFailure((T) item, error); listener.onItemAdded(item, position); } }); if (callback != null) callback.onFailure((T) item, error); } }); }).start(); } // 获取不可修改的列表视图(用于RecyclerView) public List<T> getViewList() { return Collections.unmodifiableList(internalList); } // 实体变更监听器 private static class EntityChangeListener<T extends SynchronizableEntity> implements PropertyChangeListener { @Override public void propertyChange(PropertyChangeEvent evt) { ((T) evt.getSource()).sync(null); } } private void registerListener(T element) { if (element != null) { element.addPropertyChangeListener(entityChangeListener); } } private void unregisterListener(T element) { if (element != null) { element.removePropertyChangeListener(entityChangeListener); } } } removePropertyChangeListener?
最新发布
06-25
/** * 核心数据存储容器 * 职责: * - 管理所有实体类的全局存储列表 * - 维护实体类型与列表的映射关系 * - 提供预置对象管理 */ public class DataCore { // ====================== 实体存储区 ====================== public final SynchronizedList<Bancai> bancais = new SynchronizedList<>(Bancai.class); public final SynchronizedList<Caizhi> caizhis = new SynchronizedList<>(Caizhi.class); // 其他列表声明... (与原始Data类相同) // 实体类型与列表的映射表 public final Map<Class, SynchronizedList<SynchronizableEntity>> dataCollectionMap = new ConcurrentHashMap<>(); public DataCore() { initializeDataMap(); } private void initializeDataMap() { try { for (Field field : this.getClass().getDeclaredFields()) { if (SynchronizedList.class.equals(field.getType())) { SynchronizedList<?> list = (SynchronizedList<?>) field.get(this); if (list != null) { dataCollectionMap.put(list.getEntityType(), (SynchronizedList<SynchronizableEntity>) list); } } } } catch (IllegalAccessException e) { throw new RuntimeException("初始化dataCollectionMap失败", e); } } /** * 确保每个列表都有预置对象 */ public void ensurePreservedObjects() { addIfMissing(bancais, Bancai.class); addIfMissing(caizhis, Caizhi.class); // 其他列表检查... } private <T extends SynchronizableEntity> void addIfMissing( List<T> list, Class<T> clazz ) { if (!containsPreservedObject(list)) { list.add(createInstance(clazz)); } } private <T extends SynchronizableEntity> boolean containsPreservedObject(List<T> list) { return list.stream().anyMatch(SynchronizableEntity::isPreservedObject); } /** * 创建带默认值的实体实例 */ public <T> T createInstance(Class<T> clazz) { // 实现与原始Data类相同... } }
06-17
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值