Java中ArrayList同步的2种方法分享
前言:
arrayList
的实现是默认不同步的。这意味着如果一个线程在结构上修改它并且多个线程同时访问它,它必须在外部同步。结构修改意味着从列表中添加或删除元素或显式调整后备数组的大小。改变现有元素的值不是结构修改。
有两种方法可以创建同步Arraylist:
- 1. Collections.synchronizedList() 方法。
- 2. 使用 CopyOnWriteArrayList。
方法1:使用 Collections.synchronizedList() 方法
要进行串行访问,必须通过返回列表完成对后备列表的所有访问。
在迭代返回的列表时,用户必须手动同步它。因为在执行add()等方法的时候是加了synchronized
关键字的,但是iterator()却没有加。所以在使用的时候需要加上synchronized
。
// Java program to demonstrate working of // Collections.synchronizedList import java.util.*; class GFG { public static void main (String[] args) { List<String> list = Collections.synchronizedList(new ArrayList<String>()); list.add("practice"); list.add("code"); list.add("quiz"); synchronized(list) { // must be in synchronized block Iterator it = list.iterator(); while (it.hasNext()) System.out.println(it.next()); } } }
方法 2:使用 CopyOnWriteArrayList
ArrayList
的线程安全变体,其中所有可变操作(例如添加、设置、删除...)都是通过创建底层数组的单独副本来实现的。它通过创建 List 的单独副本来实现线程安全,这与 vector 或其他集合用于提供线程安全的方式不同。
- 当我们不能或不想同步遍历,但需要防止并发线程之间的干扰时,它很有用。
- 这是昂贵的,因为每次写入操作都涉及单独的数组副本(例如添加,设置,删除......)
- 当你有List并且需要遍历它的元素并且不经常修改它时,它是非常有效的。
即使在创建迭代器后修改了 copyOnWriteArrayList
,迭代器也不会抛出ConcurrentModificationException
,因为迭代器正在迭代 ArrayList 的单独副本,而写操作正在 ArrayList 的另一个副本上发生。
// Java program to illustrate the thread-safe ArrayList. import java.io.*; import java.util.Iterator; import java.util.concurrent.CopyOnWriteArrayList; class GFG { public static void main (String[] args) { // creating a thread-safe Arraylist. CopyOnWriteArrayList<String> threadSafeList = new CopyOnWriteArrayList<String>(); // Adding elements to synchronized ArrayList threadSafeList.add("geek"); threadSafeList.add("code"); threadSafeList.add("practice"); System.out.println("Elements of synchronized ArrayList :"); // Iterating on the synchronized ArrayList using iterator. Iterator<String> it = threadSafeList.iterator(); while (it.hasNext()) System.out.println(it.next()); } }
如果我们尝试通过迭代器自己的方法修改 CopyOnWriteArrayList 会发生什么?
如果您尝试通过迭代器自己的方法(例如 add()、set()、remove())修改CopyOnWriteArrayList
,它会抛出 UnsupportedOperationException 。
// Java program to illustrate the thread-safe ArrayList import java.io.*; import java.util.Iterator; import java.util.concurrent.CopyOnWriteArrayList; class GFG { public static void main (String[] args) { // creating a thread-safe Arraylist. CopyOnWriteArrayList<String> threadSafeList = new CopyOnWriteArrayList<String>(); // Adding elements to synchronized ArrayList threadSafeList.add("geek"); threadSafeList.add("code"); threadSafeList.add("practice"); System.out.println("Elements of synchronized ArrayList :"); // Iterating on the synchronized ArrayList using iterator. Iterator<String> it = threadSafeList.iterator(); while (it.hasNext()) { String str = it.next(); it.remove(); } } }
CopyOnWriteArrayList 的其他构造函数:
- 1. CopyOnWriteArrayList(Collection<? extends E> c):创建一个包含指定集合元素的列表,按照集合迭代器返回的顺序。
- 2. CopyOnWriteArrayList(E[] toCopyIn):创建一个包含给定数组副本的列表。
向量同步时为什么要使用arrayList?
- 性能:
Vector
是同步和线程安全的,因此,它比ArrayList
稍慢。 - 功能: Vector 在每个单独的操作级别进行同步。通常,程序员喜欢同步整个操作序列。同步单个操作既不安全又慢。
- Vectors obsolete:向量被认为是过时的,并且在 java 中被非正式地弃用。此外,vector 对几乎从未完成的每个单独操作进行同步。大多数java程序员更喜欢使用
ArrayList
,因为如果他们需要进行同步,他们可能无论如何都会显式地同步arrayList。
以下是 Java 中 ArrayList
和 CopyOnWriteArrayList
类之间的显着差异。
数组列表 | 复制写入数组列表 | |
---|---|---|
同步 | ArrayList 不同步。 | CopyOnWriteArrayList 是同步的。 |
线程安全 | ArrayList 不是线程安全的。 | CopyOnWriteArrayList 是线程安全的。 |
迭代器类型 | ArrayList 迭代器是快速失败的,如果在迭代过程中发生并发修改,则 ArrayList 会抛出 ConcurrentModificationException。 | CopyOnWriteArrayList 是故障安全的,它在迭代过程中永远不会抛出 ConcurrentModificationException。其背后的原因是 CopyOnWriteArrayList 每次修改时都会创建一个新的数组列表。 |
删除操作 | ArrayList 迭代器支持在迭代过程中移除元素。 | 如果在迭代期间尝试删除元素,则 CopyOnWriteArrayList.remove() 方法会引发异常。 |
表现 | ArrayList 更快。 | CopyOnWriteArrayList 比 ArrayList 慢。 |
从 Java 版本开始 | 1.2 | 1.5 |
到此这篇关于Java中ArrayList同步的2种方法分享的文章就介绍到这了,更多相关Java中ArrayList同步内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
相关文章
IntelliJ IDEA创建maven多模块项目(图文教程)
这篇文章主要介绍了IntelliJ IDEA创建maven多模块项目(图文教程),非常具有实用价值,需要的朋友可以参考下2017-09-09java.io.UncheckedIOException: Cannot delete C
本文主要介绍了java.io.UncheckedIOException: Cannot delete C:\Users\guo\AppData\Local\Temp\tomcat.8081问题,具有一定的参考价值,感兴趣的可以了解一下2024-05-05解决Spring Security升级到5.5.7、5.6.4及以上启动报错出现版本不兼容的问题
这篇文章主要介绍了解决Spring Security升级到5.5.7、5.6.4及以上启动报错出现版本不兼容的问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教2024-08-08基于Eclipse 的JSP/Servlet的开发环境的搭建(图文)
本文将会详细地展示如何搭建JSP的开发环境。本次教程使用的是最新版的Eclipse 2018-09编辑器和最新版的Apache Tomcat v9.0,步骤详细,内容详尽,适合零基础学者作为学习参考2018-12-12Spring Boot中使用Spring Retry重试框架的操作方法
这篇文章主要介绍了Spring Retry 在SpringBoot 中的应用,介绍了RetryTemplate配置的时候,需要设置的重试策略和退避策略,需要的朋友可以参考下2022-04-04解决try-catch捕获异常信息后Spring事务失效的问题
这篇文章主要介绍了解决try-catch捕获异常信息后Spring事务失效的问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教2021-06-06IDEA2019.2.2配置Maven3.6.2打开出现Unable to import Maven project
这篇文章主要介绍了IDEA2019.2.2配置Maven3.6.2打开出现Unable to import Maven project,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧2020-12-12
最新评论