首页 > 编程语言 >Java中ArrayList同步的2种方法分享

Java中ArrayList同步的2种方法分享

时间:2022-12-14 10:06:00浏览次数:139  
标签:同步 Java 迭代 ArrayList CopyOnWriteArrayList add 线程 分享

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,CopyOnWriteArrayList,add,线程,分享
From: https://blog.51cto.com/u_15733182/5935458

相关文章

  • 利用CSS、JavaScript及Ajax实现图片预加载的三大方法
    预加载图片是提高用户体验的一个很好方法。图片预先加载到浏览器中,访问者便可顺利地在你的网站上冲浪,并享受到极快的加载速度。这对图片画廊及图片占据很大比例的网站来说......
  • 24_Java网络编程
    Java_网络编程一、网络编程入门友情提示使用网络编程代码时,注意连接网络的变化(IP地址会变),可能不注意的话导致无法正确运行stocket:套接字1、网络编程......
  • 新装Eclipse运行Java程序报错Exception in thread "main" java.lang.UnsupportedClass
    错误现象:  Exceptioninthread"main"java.lang.UnsupportedClassVersionError:views/LoginFramehasbeencompiledbyamorerecentversionoftheJavaRunt......
  • Java Object转实体(自用)
    JavaObject转实体一、遇到的问题在从RedisHash根据一些条件(类似*|0)查询对应的HashValue时,发现在Java里获取RedisHash中的Value其实是字符串的形式。我尝试使用了fa......
  • Java复习笔记-抽象、接口、内部类、枚举
    1抽象abstractclass类名{//方法(实现的,抽象方法)//属性}1.1抽象类的细节1).抽象类不能被实例化2).可以有不是抽象的......
  • java和ssm开发的经销系统
    简介Ssm服装经销系统,主要分为6个角色:管理员、资料员、采购员、仓库员、售卖员、财务。采购员进行采购入库;仓库员进行采购入库、退货入库、提货出库、折损出库等库存管理;售卖......
  • java和vue车辆管理系统车管所系统
    简介车辆管理系统车管所系统,管理员添加车主信息,车主提交自己的车辆信息,管理员审核车辆,对车辆行进年检,统计,记录车辆违规信息。车主可以查看自己的车辆信息、投诉、查看自己的......
  • java和vue的大学生奖学金助学金系统奖学金系统助学金系统
    简介大学生奖学金助学金系统。学生申请自己需要的奖助学金,上传证明材料。该学院的辅导员可以下载学生的证明材料以及根据学生的综合成绩来审核是否通过,若不通过请输入不通过......
  • java和vue的狱警管理系统监狱系统狱务管理系统
    简介狱警管理系统监狱系统狱务管理系统,主要是管理罪犯教育改造、劳动改造、案件管理,罪犯信息管理等演示视频​​https://www.bilibili.com/video/BV1VG411P7YL/?zw&vd_sour......
  • java和vue开发的电子书系统自动检测敏感词小说网站
    简介电子书系统,注册用户上传txt,系统自动检测敏感词汇并且自动生成章节。管理员审核电子书,管理电子书分类和用户,评论等。注册用户可以搜索浏览电子书,在线阅读和下载电子书。......