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

 更新时间:2022年03月17日 16:44:04   作者:小锋学长生活大爆炸  
这篇文章主要分享了Java中ArrayList同步的2种方法,Collections.synchronizedList()的方法,这个方法要进行串行访问以及使用CopyOnWriteArrayList,下面分享内容需要的小伙伴可以参考一下

前言:

        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.21.5

到此这篇关于Java中ArrayList同步的2种方法分享的文章就介绍到这了,更多相关Java中ArrayList同步内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Spring Security实现微信公众号网页授权功能

    Spring Security实现微信公众号网页授权功能

    这篇文章主要介绍了Spring Security中实现微信网页授权,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-08-08
  • java中类与对象的使用详情

    java中类与对象的使用详情

    这篇文章主要介绍了java中类与对象的使用详情,面向对象是通过类和对象去描述和代表万千事物对象的,首先我们需要知道如何去定义一个类,下面文章我们详细介绍两者的使用方法,需要的小伙伴可以参考一下
    2022-05-05
  • Java中的RestTemplate使用详解

    Java中的RestTemplate使用详解

    这篇文章主要介绍了Java中的RestTemplate使用详解,Spring内置了RestTemplate作为Http请求的工具类,简化了很多操作,虽然Spring5推出了WebClient,但是整体感觉还是RestTemplate用起来更简单方便一些,需要的朋友可以参考下
    2023-10-10
  • Java线程中start和run方法全面解析

    Java线程中start和run方法全面解析

    这篇文章主要介绍了Java线程中start和run方法的相关资料,非常不错,具有参考借鉴价值,需要的朋友可以参考下
    2016-08-08
  • Spring boot读取外部化配置的方法

    Spring boot读取外部化配置的方法

    大家好,本篇文章主要讲的是Spring boot读取外部化配置的方法,感兴趣的同学赶快来看一看吧,对你有帮助的话记得收藏一下
    2022-02-02
  • spring-boot实现增加自定义filter(新)

    spring-boot实现增加自定义filter(新)

    本篇文章主要介绍了spring-boot实现增加自定义filter(新),小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-05-05
  • 怎样提高mybatis-plus中saveBatch方法的效率

    怎样提高mybatis-plus中saveBatch方法的效率

    这篇文章主要介绍了怎样提高mybatis-plus中saveBatch方法的效率问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-07-07
  • Java常用工具类汇总 附示例代码

    Java常用工具类汇总 附示例代码

    这篇文章主要介绍了Java常用工具类汇总 附示例代码,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-04-04
  • Java HashMap中除了死循环之外的那些问题

    Java HashMap中除了死循环之外的那些问题

    这篇文章主要介绍了Java HashMap中除了死循环之外的那些问题,这些问题大致可以分为两类,程序问题和业务问题,下面文章我们一个一个来看,需要的小伙伴可以参考一下
    2022-05-05
  • springboot集成es详解

    springboot集成es详解

    这篇文章主要介绍了springboot集成es,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-11-11

最新评论