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

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

arrayList 的实现是默认不同步的。这意味着如果一个线程在结构上修改它并且多个线程同时访问它,它必须在外部同步。结构修改意味着从列表中添加或删除元素或显式调整后备数组的大小。改变现有元素的值不是结构修改。

有两种方法可以创建同步Arraylist:

    1. Collections.synchronizedList() 方法。
    1. 使用 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): 创建一个包含指定集合元素的列表,按照集合迭代器返回的顺序。
    1. 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##程序员#
全部评论
收获太大了
点赞 回复 分享
发布于 2022-10-18 12:10 陕西

相关推荐

(黑话警告⚠️:hc=岗位数量,&nbsp;mt=导师,&nbsp;ld=直属领导,&nbsp;cr=代码审查)25年1月,我加入了字节某前端团队,并期望能在这里待到秋招并尝试转正。然而,就在上周,ld&nbsp;找我1v1,告诉我,我的能力和团队预期不太匹配,并和我劝退。晴天霹雳吗?肯定是有的。那一刻,脑子里嗡嗡作响,各种情绪翻涌。但冷静下来想想,这几个月,自己在能掌控的范围内,确实有不少地方做得不尽如人意。所以,我想把这段不算成功的经历复盘一下,希望能给同样在努力转正的你提个醒,避开我踩过的坑。一、ld&nbsp;的要求要注意刚进组时,ld就和我聊过转正的事。我当时发问:“咱们这儿有hc&nbsp;吗?”&nbsp;ld没直接回答,只是说:“看能力,能力到了...
牛客上的彭于晏:过来人告诉你,入职后要做的第一件事儿不是说主动找活儿做,你要先学会融入团队,摸清ld的性格,投其所好。然后才是展示你的能力,能力上可以说技术或者业务,以业务能力为主,技术能力为辅。优先保证自己对业务需求的开发保证质量效率,然后再谈技术的问题,不要你觉得啥啥啥不行就想着整体优化了(发现校招生最喜欢干这事儿),我工作快5年了发现搞这种的最后都没啥好的结果,产出没有还引入新的bug,校招或者实习的水平看到的问题别人看不到嘛?为什么别人不去搞?浪费时间还没收益的事儿不要去做,技术上的能力体现在对于一个新需求,在不符合现在业务发展的架构设计上,你能拿出好的技术方案同时能考虑到后续业务发展逐渐将技术架构引入合理的架构,这是一个漫长的过程而不是一次性的
点赞 评论 收藏
分享
xwqlikepsl:感觉很厉害啊,慢慢找
点赞 评论 收藏
分享
04-27 08:59
常州大学 Java
牛客139242382号:《两门以上汇编语言》
点赞 评论 收藏
分享
评论
3
2
分享

创作者周榜

更多
牛客网
牛客企业服务