避免list的并发修改异常的几种方式

简介: 避免list的并发修改异常的几种方式

避免list的并发修改异常的几种方式

1、使用list的snapshot,遍历它的副本

使用如下:com.bumptech.glide.manager.ActivityFragmentLifecycle#onStart()

for (LifecycleListener lifecycleListener : Util.getSnapshot(lifecycleListeners)) {
  lifecycleListener.onStart();
}

具体实现如下:
com.bumptech.glide.util.Util:

/**
 * Returns a copy of the given list that is safe to iterate over and perform actions that may
 * modify the original list.
 *
 * <p>See #303, #375, #322, #2262.
 */
@NonNull
@SuppressWarnings("UseBulkOperation")
public static <T> List<T> getSnapshot(@NonNull Collection<T> other) {
  // toArray creates a new ArrayList internally and does not guarantee that the values it contains
  // are non-null. Collections.addAll in ArrayList uses toArray internally and therefore also
  // doesn't guarantee that entries are non-null. WeakHashMap's iterator does avoid returning null
  // and is therefore safe to use. See #322, #2262.
  List<T> result = new ArrayList<>(other.size());
  for (T item : other) {
    if (item != null) {
      result.add(item);
    }
  }
  return result;
}

2、使用CopyOnWriteArrayList

具体可以参考给ViewTreeObserver添加OnGlobalLayoutListener:


// Non-recursive listeners use CopyOnWriteArray
// Any listener invoked from ViewRootImpl.performTraversals() should not be recursive
@UnsupportedAppUsage
private CopyOnWriteArray<OnGlobalLayoutListener> mOnGlobalLayoutListeners;


/**
 * Register a callback to be invoked when the global layout state or the visibility of views
 * within the view tree changes
 *
 * @param listener The callback to add
 *
 * @throws IllegalStateException If {@link #isAlive()} returns false
 */
public void addOnGlobalLayoutListener(OnGlobalLayoutListener listener) {
    checkIsAlive();


    if (mOnGlobalLayoutListeners == null) {
        mOnGlobalLayoutListeners = new CopyOnWriteArray<OnGlobalLayoutListener>();
    }


    mOnGlobalLayoutListeners.add(listener);
}

/**
 * Remove a previously installed global layout callback
 *
 * @param victim The callback to remove
 *
 * @throws IllegalStateException If {@link #isAlive()} returns false
 * 
 * @see #addOnGlobalLayoutListener(OnGlobalLayoutListener)
 */
public void removeOnGlobalLayoutListener(OnGlobalLayoutListener victim) {
    checkIsAlive();
    if (mOnGlobalLayoutListeners == null) {
        return;
    }
    mOnGlobalLayoutListeners.remove(victim);
}

/**
 * Notifies registered listeners that a global layout happened. This can be called
 * manually if you are forcing a layout on a View or a hierarchy of Views that are
 * not attached to a Window or in the GONE state.
 */
public final void dispatchOnGlobalLayout() {
    // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to
    // perform the dispatching. The iterator is a safe guard against listeners that
    // could mutate the list by calling the various add/remove methods. This prevents
    // the array from being modified while we iterate it.
    final CopyOnWriteArray<OnGlobalLayoutListener> listeners = mOnGlobalLayoutListeners;
    if (listeners != null && listeners.size() > 0) {
        CopyOnWriteArray.Access<OnGlobalLayoutListener> access = listeners.start();
        try {
            int count = access.size();
            for (int i = 0; i < count; i++) {
                access.get(i).onGlobalLayout();
            }
        } finally {
            listeners.end();
        }
    }
}

/**addOnGlobalLayoutListener
 * Register a callback to be invoked when the global layout state or the visibility of views
 * within the view tree changes
 *
 * @param listener The callback to add
 *
 * @throws IllegalStateException If {@link #isAlive()} returns false
 */
public void addOnGlobalLayoutListener(OnGlobalLayoutListener listener) {
    checkIsAlive();


    if (mOnGlobalLayoutListeners == null) {
        mOnGlobalLayoutListeners = new CopyOnWriteArray<OnGlobalLayoutListener>();
    }


    mOnGlobalLayoutListeners.add(listener);
}

/**
 * Notifies registered listeners that a global layout happened. This can be called
 * manually if you are forcing a layout on a View or a hierarchy of Views that are
 * not attached to a Window or in the GONE state.
 */
public final void dispatchOnGlobalLayout() {
    // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to
    // perform the dispatching. The iterator is a safe guard against listeners that
    // could mutate the list by calling the various add/remove methods. This prevents
    // the array from being modified while we iterate it.
    final CopyOnWriteArray<OnGlobalLayoutListener> listeners = mOnGlobalLayoutListeners;
    if (listeners != null && listeners.size() > 0) {
        CopyOnWriteArray.Access<OnGlobalLayoutListener> access = listeners.start();
        try {
            int count = access.size();
            for (int i = 0; i < count; i++) {
                access.get(i).onGlobalLayout();
            }
        } finally {
            listeners.end();
        }
    }
}
相关文章
|
1月前
|
安全
List并发线程安全问题
【10月更文挑战第21天】`List` 并发线程安全问题是多线程编程中一个非常重要的问题,需要我们认真对待和处理。只有通过不断地学习和实践,我们才能更好地掌握多线程编程的技巧和方法,提高程序的性能和稳定性。
142 59
|
6月前
|
安全 Java
java线程之List集合并发安全问题及解决方案
java线程之List集合并发安全问题及解决方案
971 1
|
7月前
|
安全 Java API
Java并发 - J.U.C并发容器类 list、set、queue
Queue API 阻塞是通过 condition 来实现的,可参考 Java 并发 - Lock 接口 ArrayBlockingQueue 阻塞 LinkedBlockingQueue 阻塞 ArrayQueue 非阻塞 LinkedQueue 非阻塞
|
缓存 监控 Java
游戏服务器开服异常Check List
游戏服务器开服异常Check List
59 0
|
安全 Java 索引
java中有哪些并发的List?只知道一种的就太逊了
java中有很多list,但是原生支持并发的并不多,我们在多线程的环境中如果想同时操作同一个list的时候,就涉及到了一个并发的过程,这时候我们就需要选择自带有并发属性的list,那么java中的并发list到底有哪些呢?今天要给大家介绍的是`ArrayList`、`CopyOnWriteArrayList`、`ConcurrentLinkedDeque`这几个。
|
Java 数据格式 Spring
SpringBoot中@Value注解注入List或Map数据格式出现异常
在做一个小demo的时候、做的例子是我想在程序运行时将一些数据放入到配置类中的属性中、我想到可以通过yaml配置的数据映射到实体类中的属性中、我在想通过这种形式能不能映射。
|
安全 Java
Java Review - 并发编程_并发List_CopyOnWriteArrayList源码剖析
Java Review - 并发编程_并发List_CopyOnWriteArrayList源码剖析
72 0
一个关于List的IndexOutOfBoundsException异常记录
一个关于List的IndexOutOfBoundsException异常记录
117 0
|
SQL 关系型数据库 MySQL
解决Mysql5.7以上版本, 使用group by抛出Expression #1 of SELECT list is not in GROUP BY clause and contains no异常
解决Mysql5.7以上版本, 使用group by抛出Expression #1 of SELECT list is not in GROUP BY clause and contains no异常
132 0
有关使用Arrays.asList(array) 转换成List集合之后,对其进行操作抛出UnsupportedOperationException异常的问题
有关使用Arrays.asList(array) 转换成List集合之后,对其进行操作抛出UnsupportedOperationException异常的问题
108 0