默认情况下,ArrayList的实现不同步。这意味着,如果一个线程在结构上修改了它,并且多个线程同时访问它,那么它必须在外部同步。结构修改意味着从列表中添加或删除元素,或显式调整支持数组的大小。更改现有图元的值不是结构修改。
有两种方法可以创建同步的ArrayList。
1.收藏。synchronizedList()方法。 2.使用CopyOnWriteArrayList。
方法1:使用集合。synchronizedList()方法
要进行串行访问,必须通过返回的列表完成对支持列表的所有访问。用户必须 手动 在遍历返回的列表时对其进行同步。
public static List<T> synchronizedList(List<T> list)
- 接受一个列表,该列表可能是 列表 界面e、 g.ArrayList,LinkedList。
- 返回由指定列表支持的同步(线程安全)列表。
- 参数列表是要包装在同步列表中的列表。
- T代表 通用的
JAVA
// 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()); } } } |
practicecodequiz
方法2:使用CopyOnWriteArrayList
CopyOnWriteArrayList<T> threadSafeList = new CopyOnWriteArrayList<T>();
- 创建一个空列表。
- 它实现了 列表 界面
- 它是ArrayList的线程安全变体。
- T代表泛型
ArrayList的一种线程安全变体,其中包含所有变异操作(例如,添加、设置、删除..)通过创建基础文件的单独副本来实现 大堆 。它通过创建列表的单独副本来实现线程安全,该副本不同于用于提供线程安全的vector或其他集合。
- 当你不能或不想做的时候,它很有用 使同步 遍历还需要防止并发线程之间的干扰。
- 它是 花钱多的 因为它涉及到单独的 数组副本 每次写入操作(例如,添加、设置、删除)
- 当你有 列表 需要遍历它的元素,不要经常修改它。
迭代器不会抛出 ConcurrentModificationException 即使创建迭代器后修改了copyOnWriteArrayList。迭代器正在对ArrayList的单独副本进行迭代,而写操作正在对ArrayList的另一个副本进行。
JAVA
// 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()); } } |
Elements of synchronized ArrayList :geekcodepractice
如果我们试图通过 迭代器方法?
如果您试图修改,它会抛出UnsupportedOperationException CopyOnWriteArrayList 通过迭代器自己的方法(例如add()、set()、remove())。
JAVA
// 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(); } } } |
运行时错误:
Exception in thread "main" java.lang.UnsupportedOperationException at java.util.concurrent.CopyOnWriteArrayList$COWIterator.remove (CopyOnWriteArrayList.java:1176) at GFG.main(File.java:28)
CopyOnWriteArrayList的其他构造函数
1. CopyOnWriteArrayList(集合c) :创建一个包含指定集合元素的列表,按集合迭代器返回的顺序排列。
2. CopyOnWriteArrayList(E[]到copyin) :创建包含给定数组副本的列表。
向量同步时为什么使用ArrayList?
- 性能: 向量是 同步的 而且线程安全,正因为如此,它比ArrayList稍慢一些。
- 功能: 矢量在每个单独操作的级别进行同步。通常,程序员喜欢同步整个操作序列。同步单个操作既不安全,也较慢。
- 向量过时: 在java中,向量被认为是过时的,并被非正式地弃用。此外,向量在每个单独的操作上都是同步的,这几乎是从未完成过的。大多数java程序员更喜欢使用ArrayList,因为如果需要同步,他们可能会显式地同步ArrayList。
必须阅读: Java中的向量与数组列表
本文由 尼茨海伦德拉 .如果你喜欢GeekSforgek,并想贡献自己的力量,你也可以使用 写极客。组织 或者把你的文章寄去评论-team@geeksforgeeks.org.看到你的文章出现在Geeksforgeks主页上,并帮助其他极客。如果您发现任何不正确的地方,或者您想分享有关上述主题的更多信息,请写下评论。