处理线程安全的列表CopyOnWriteArrayList 和Collections.synchronizedList
ConcurrentModificationException 是 Java 中的一种异常,用于指示在迭代集合时,该集合的结构发生了并发修改。
(图片来源网络,侵删)
在 Java 中,许多集合类(如 ArrayList, HashMap 等)都不是线程安全的。如果一个线程在迭代集合的同时,另一个线程修改了该集合的结构(如添加、删除元素),就可能导致 ConcurrentModificationException 异常的抛出。
这种异常通常在使用迭代器遍历集合时发生,迭代器在创建时会记录集合的结构状态,如果在迭代期间发现集合结构已经发生了变化,就会抛出 ConcurrentModificationException。
CopyOnWriteArrayList 和 Collections.synchronizedList都是 Java 中用于处理线程安全的列表操作的工具类,但它们在实现和适用场景上有一些区别。
CopyOnWriteArrayList
作用:
- CopyOnWriteArrayList 是一种适合读操作远多于写操作的线程安全列表实现。
- 写操作(如添加、修改、删除元素)会创建一个当前列表的副本,对副本进行操作,写操作完成后将副本替换原来的列表。这保证了写操作不会影响到正在进行的读操作,从而避免了并发修改异常 (ConcurrentModificationException)。
优点:
- 适合读多写少的场景,因为读操作不需要加锁,性能较高。
- 写操作通过复制数组来实现线程安全,避免了使用显式锁带来的性能损失。
缺点:
- 写操作的性能相对较低,因为每次写操作都要复制整个数组。
- 内存消耗较大,因为每次写操作都会复制数组。
示例用法:
import java.util.concurrent.CopyOnWriteArrayList; import java.util.List; List list = new CopyOnWriteArrayList(); list.add(1); list.add(2); list.add(3); // 在多线程环境中安全地进行读写操作 for (Integer num : list) { System.out.println(num); } // 注意:不建议在迭代过程中进行写操作,因为迭代器不支持修改操作Collections.synchronizedList
作用:
- Collections.synchronizedList 是通过包装普通的 ArrayList(或其他 List 实现)来生成线程安全的列表。
- 它使用了一个对象级的锁(即在列表对象上加锁),来确保多个线程不能同时修改列表,从而保证线程安全。
优点:
- 相对于 CopyOnWriteArrayList,它在写操作时不需要复制整个数组,因此写操作的性能可能会更好一些。
- 使用简单,通过静态方法 Collections.synchronizedList 就可以获取线程安全的列表。
缺点:
- 在高并发环境下,由于使用了对象级的锁,可能会造成性能瓶颈。
- 需要手动管理使用到的锁,编写代码时需要确保在所有访问列表的地方都正确地加锁。
示例用法:
import java.util.Collections; import java.util.List; import java.util.ArrayList; List list = Collections.synchronizedList(new ArrayList()); list.add(1); list.add(2); list.add(3); // 手动在多线程环境中通过 synchronized 同步块或方法来安全地访问 list synchronized (list) { for (Integer num : list) { System.out.println(num); } }区别比较
-
性能特征:
- CopyOnWriteArrayList 适合读多写少的场景,读操作高效,写操作较慢(读操作访问同一份列表,不加锁)。
- Collections.synchronizedList 在写操作的性能上可能会优于 CopyOnWriteArrayList,但在高并发情况下可能引入较大的性能开销(读写操作都加上锁)。
-
内部实现:
- CopyOnWriteArrayList 写操作通过复制数组来实现线程安全。
- Collections.synchronizedList 使用 synchronized 关键字或者内部锁来保证线程安全。
-
使用方式:
- CopyOnWriteArrayList 直接使用构造函数或者 add 等方法来操作列表,不需要额外的同步控制。
- Collections.synchronizedList 需要在使用时通过 synchronized 关键字或者同步块来手动管理线程安全。
选择合适的列表实现
- 读多写少:推荐使用 CopyOnWriteArrayList,因为它可以提供较高的读取性能。
- 读写操作均衡或者写多读少:考虑使用 Collections.synchronizedList 或其他更复杂的并发控制方式,根据具体情况选择合适的同步策略。
总结来说,根据应用场景和性能要求选择合适的线程安全列表实现,能够有效地避免并发访问带来的问题。
-
免责声明:我们致力于保护作者版权,注重分享,被刊用文章因无法核实真实出处,未能及时与作者取得联系,或有版权异议的,请联系管理员,我们会立即处理! 部分文章是来自自研大数据AI进行生成,内容摘自(百度百科,百度知道,头条百科,中国民法典,刑法,牛津词典,新华词典,汉语词典,国家院校,科普平台)等数据,内容仅供学习参考,不准确地方联系删除处理! 图片声明:本站部分配图来自人工智能系统AI生成,觅知网授权图片,PxHere摄影无版权图库和百度,360,搜狗等多加搜索引擎自动关键词搜索配图,如有侵权的图片,请第一时间联系我们,邮箱:ciyunidc@ciyunshuju.com。本站只作为美观性配图使用,无任何非法侵犯第三方意图,一切解释权归图片著作权方,本站不承担任何责任。如有恶意碰瓷者,必当奉陪到底严惩不贷!
