java中有哪些并发的List?只知道一种的就太逊了

java,哪些,并发,list,知道,一种 · 浏览次数 : 324

小编点评

**ArrayList** * **优点:** * 简单易用 * 高效的随机访问 * **缺点:** * 非线程安全 * 需要外部同步 **CopyOnWriteArrayList** * **优点:** * 线程安全 * 适用于读多写少的情况 **ConcurrentLinkedDeque** * **优点:** * 高并发 * 低延迟 * 支持随机访问 **比较** | **属性** | **ArrayList** | **CopyOnWriteArrayList** | **ConcurrentLinkedDeque** | |---|---|---|---| | 线程安全性 | 非线程安全 | 线程安全 | 支持线程安全 | | 写操作开销 | 较高 | 较低 | 较高 | | 数据访问 | 随机访问 | 顺序访问 | 顺序访问 | | 性能 | 较高 | 中等 | 较低 |

正文

java中有很多list,但是原生支持并发的并不多,我们在多线程的环境中如果想同时操作同一个list的时候,就涉及到了一个并发的过程,这时候我们就需要选择自带有并发属性的list,那么java中的并发list到底有哪些呢?今天要给大家介绍的是ArrayListCopyOnWriteArrayListConcurrentLinkedDeque这几个。

各种list的优缺点

当涉及到并发编程时,不同的 List 实现具有各自的优点和缺点。下面是对 ArrayListCopyOnWriteArrayListConcurrentLinkedDeque 的优缺点进行详细比较的描述:

ArrayList:

  • 优点:
    • 简单易用:ArrayList 是 Java 中最基本的动态数组,易于理解和使用。
    • 高效的随机访问:由于内部基于数组实现,因此具有良好的随机访问性能。
  • 缺点:
    • 非线程安全:ArrayList 不是线程安全的,当多个线程同时修改它时会出现竞态条件。
    • 需要外部同步:为了使 ArrayList 在多线程环境下安全,需要额外的同步措施,如使用 Collections.synchronizedList

CopyOnWriteArrayList:

  • 优点:
    • 线程安全:CopyOnWriteArrayList 是线程安全的,多个线程可以同时读取而不会出现问题。
    • 适用于读多写少的情况:由于写操作会复制整个数组,适用于读多写少的情况,例如日志记录。
  • 缺点:
    • 写操作开销大:每次写操作都会复制整个列表,因此写操作的开销较大,不适合高频写入操作。
    • 数据不是实时的:由于写操作的复制过程,读操作可能会看到旧数据,因此不适用于需要实时数据的场景。

ConcurrentLinkedDeque:

  • 优点:
    • 高并发:ConcurrentLinkedDeque 针对高并发读写进行了优化,适用于需要高并发处理的情况。
    • 低延迟:添加和删除操作的性能很好,不会导致锁争用。
  • 缺点:
    • 不支持随机访问:ConcurrentLinkedDeque 不支持随机访问元素,因为它是一个双端队列,只能从队头和队尾进行操作。
    • 不适用于所有场景:不适合需要随机访问的场景,例如需要根据索引查找元素的情况。

总的来说,选择哪种 List 实现取决于您的具体需求。如果您需要高度并发且读写操作相对平衡,ConcurrentLinkedDeque 可能是更好的选择。如果您主要进行读操作且能够容忍写操作的开销,CopyOnWriteArrayList 是一个不错的选择。如果您只在单线程环境下操作,ArrayList 可能是更简单的选择,但需要注意同步问题。

他们的实现原理

理解这些并发 List 实现的原理对于正确使用它们非常重要。以下是这些 List 的实现原理:

ArrayList:

  • 实现:ArrayList 基于动态数组实现。它内部维护一个对象数组,可以根据需要进行自动扩展。
  • 原理:ArrayList 支持随机访问,因为可以通过索引直接访问元素。添加元素时,它会检查容量是否足够,如果不够,会创建一个更大的数组并将元素复制到新数组中。这可能导致内部数组的重新分配和复制,因此在多线程环境下需要额外的同步来确保线程安全。

CopyOnWriteArrayList:

  • 实现:CopyOnWriteArrayList 也是基于数组实现的,但与普通的 ArrayList 不同,它在写操作时不直接修改现有数组,而是创建一个新的副本。
  • 原理:读操作在不需要锁的情况下并发执行,因为它们始终访问当前的数组。写操作会复制当前数组的内容到一个新数组上,然后执行修改操作。这确保了读操作不受写操作的影响。虽然写操作需要额外的内存和复制,但读操作非常高效,适用于读多写少的场景。

ConcurrentLinkedDeque:

  • 实现:ConcurrentLinkedDeque 是一个双端队列,它使用节点来连接元素。每个节点都包含一个元素和指向前一个和后一个节点的引用。
  • 原理:在多线程环境下,ConcurrentLinkedDeque 使用CAS(比较并交换)操作来实现并发。添加元素时,它会在队头或队尾创建新的节点,然后通过CAS操作将新节点连接到队列中。删除元素时,会通过CAS来更改节点的引用,以确保线程安全。由于没有全局锁,ConcurrentLinkedDeque 允许高并发的添加和删除操作,但不支持随机访问。

总之,这些并发 List 的实现原理都是为了在多线程环境下提供高并发性能和线程安全。不同的实现方式适用于不同的使用场景。

使用举例

在多线程Java应用程序中,处理数据的并发访问是一个常见的挑战。这里将介绍四种支持并发的容器:ArrayListCopyOnWriteArrayListConcurrentLinkedDeque的用法和代码实现。

ArrayList

使用示例

以下是一个使用ArrayList的示例:

List<String> arrayList = Collections.synchronizedList(new ArrayList<>());

// 添加元素
arrayList.add("元素1");
arrayList.add("元素2");

// 迭代元素
for (String element : arrayList) {
    System.out.println(element);
}

CopyOnWriteArrayList

使用示例

下面是一个使用CopyOnWriteArrayList的示例:

CopyOnWriteArrayList<String> copyOnWriteArrayList = new CopyOnWriteArrayList<>();

// 添加元素
copyOnWriteArrayList.add("元素1");
copyOnWriteArrayList.add("元素2");

// 迭代元素
for (String element : copyOnWriteArrayList) {
    System.out.println(element);
}

ConcurrentLinkedDeque

使用示例

ConcurrentLinkedDeque的使用示例如下:

ConcurrentLinkedDeque<String> concurrentLinkedDeque = new ConcurrentLinkedDeque<>();

// 添加元素
concurrentLinkedDeque.offer("元素1");
concurrentLinkedDeque.offer("元素2");

// 获取并移除元素
String element = concurrentLinkedDeque.poll();
System.out.println("取出元素:" + element);

选择最适合您的容器

在实际应用中,您应该根据需求选择最适合的容器。如果需要高并发的读取操作,可以考虑使用CopyOnWriteArrayList。如果需要高并发的添加和移除元素操作,可以使用ConcurrentLinkedDeque。最终,根据项目要求和性能需求来选择适当的容器。

总结

Java提供了多种支持并发的容器,如ArrayList、CopyOnWriteArrayList、ConcurrentLinkedDeque。了解它们的用法和性能特点对于编写高效的多线程程序至关重要。选择正确的容器可以显著提高应用程序的性能和可靠性。

更多内容请参考 www.flydean.com

最通俗的解读,最深刻的干货,最简洁的教程,众多你不知道的小技巧等你来发现!

欢迎关注我的公众号:「程序那些事」,懂技术,更懂你!

与java中有哪些并发的List?只知道一种的就太逊了相似的内容:

java中有哪些并发的List?只知道一种的就太逊了

java中有很多list,但是原生支持并发的并不多,我们在多线程的环境中如果想同时操作同一个list的时候,就涉及到了一个并发的过程,这时候我们就需要选择自带有并发属性的list,那么java中的并发list到底有哪些呢?今天要给大家介绍的是ArrayList、CopyOnWriteArrayLis

秒懂双亲委派机制

前言 最近知识星球中,有位小伙伴问了我一个问题:JDBC为什么会破坏双亲委派机制? 这个问题挺有代表性的。 双亲委派机制是Java中非常重要的类加载机制,它保证了类加载的完整性和安全性,避免了类的重复加载。 这篇文章就跟大家一起聊聊,Java中类加载的双亲委派机制到底是怎么回事,有哪些破坏双亲委派机

Java 断言 Assert 使用教程与最佳实践

本文收录于 Github.com/niumoo/JavaNotes,Java 系列文档,数据结构与算法! 本文收录于网站:https://www.wdbyte.com/,我的公众号:程序猿阿朗 作为一个 Java 开发者,如果要问你 Java 中有哪些关键字,你可能会随口说出一串,如果问你 Java

面试官:Java类是如何被加载到内存中的?

面试连环call Java类是如何被加载到内存中的? Java类的生命周期都有哪些阶段? JVM加载的class文件都有哪些来源? JVM在加载class文件时,何时判断class文件的格式是否符合要求? 类生命周期 一个类从被加载到虚拟机内存开始,到卸载出内存为止,它的整个生命周期将会经历加载、验

在线问诊 Python、FastAPI、Neo4j — 创建药品节点

目录前提条件创建节点 Demo准备数据创建药品标签节点 在线问诊 Python、FastAPI、Neo4j — 创建节点 Neo4j 节点的标签可以理解为 Java 中的实体。 根据常规流程:首先有什么症状,做哪些对应的检查,根据检查诊断什么疾病,需要用什么药物治疗,服药期间要注意哪些饮食,需要做哪

买彩票能中大奖?用Java盘点常见的概率悖论 | 京东云技术团队

引言 《双色球头奖概率与被雷劈中的概率哪个高?》 《3人轮流射击,枪法最差的反而更容易活下来?》 让我们用Java来探索ta们! 悖论1:著名的三门问题 规则描述:你正在参加一个游戏节目,你被要求在三扇门中选择一扇:其中一扇后面有一辆车;其余两扇后面则是山羊。你选择了一道门,假设是一号门,然后知道门

解放双手!ChatGPT助力编写JAVA框架

亲爱的Javaer们,在平时编码的过程中,你是否曾想过编写一个Java框架去为开发提效?但是要么编写框架时感觉无从下手,不知道从哪开始。要么有思路了后对某个功能实现的技术细节不了解,空有想法而无法实现。如果你遇到了这些问题,看完这篇文章你也能用ChatGPT编写一个简单的JAVA框架。

java中SimpleDateFormat解析日期格式的问题

在日常写代码的过程中,我们经常要处理各种格式的日期,常见的日期格式有:“20240601”,“2024-06-01”,“2024-6-1”。如何正确地处理日期格式,尤其是对外接口中参数的日期格式,就很重要了,一个不小心就可能出现意想不到的问题。 举一个我遇到的真实例子:我们提供的对外接口中有一个参数

Java 集合中的排序算法浅析

排序是一个Java开发者,在日常开发过程中随处可见的开发内容,Java中有丰富的API可以调用使用。在Java语言中,作为集合工具类的排序方法,必定要做到通用、高效、实用这几点特征。主要探讨java中排序方法所使用的算法,以及那些是值得我们学习和借鉴的内容。文中如有理解和介绍的错误,一起学习,一起探讨,一起进步。

面试官:Java中缓冲流真的性能很好吗?我看未必

一、写在开头 上一篇文章中,我们介绍了Java IO流中的4个基类:InputStream、OutputStream、Reader、Writer,那么这一篇中,我们将以四个基类所衍生出来,应对不同场景的数据流进行学习。 二、衍生数据流分类 我们上面说了java.io包中有40多个类,都从InputS