多线程与高并发(13)——Java常见并发容器总结

news2024/12/27 13:54:54

本文总结常见的并发容器,包含ConcurrentHashMap、CopyOnWriteArrayList 、ConcurrentLinkedQueue、BlockingQueue 、ConcurrentSkipListMap,本文仅做简单的总结,不做详细的源码分析。

一、ConcurrentHashMap

HashMap不是线程安全的,ConcurrentHashMap是线程安全的。
ConcurrentHashMap的数组结构也是Node 数组 + 链表 / 红黑树,同时它采用的Synchronized 锁加CAS的机制,引用了锁升级的策略,所以性能方面没有太多问题。
在进行读操作时(几乎)不需要加锁,而在写操作时通过锁分段技术只对所操作的段加锁而不影响客户端对其它段的访问。
这里不过多总结了,回头单独写一篇文章,从源码理解ConcurrentHashMap。

二、CopyOnWriteArrayList

CopyOnWriteArrayList 是一个线程安全且读操作无锁的ArrayList ,ArrayList 是什么呢,查询速度很快,有序且可重复,底层是一个数组。

public class CopyOnWriteArrayList<E>
    implements List<E>, RandomAccess, Cloneable, java.io.Serializable {

由于日常使用时,读操作远远大于写操作,类似于ReentrantReadWriteLock(读写锁),为了进一步增加读取的效率,这里直接就不给读操作加锁,而且:写入也不会阻塞读取操作。只有写入和写入之间需要进行同步等待。
我们先看读操作源码:

@SuppressWarnings("unchecked")
    private E get(Object[] a, int index) {
        return (E) a[index];
    }

    public E get(int index) {
        return get(getArray(), index);
    }
    final Object[] getArray() {
        return array;
    }

嗯,平平无奇,就是正常获取数组的值。
再看写操作的代码,我们看add的源码:

 public boolean add(E e) {
        final ReentrantLock lock = this.lock;
        //加锁
        lock.lock();
        try {
            Object[] elements = getArray();
            int len = elements.length;
            //拷贝
            Object[] newElements = Arrays.copyOf(elements, len + 1);
            newElements[len] = e;
            setArray(newElements);
            return true;
        } finally {
        	//释放锁
            lock.unlock();
        }
    }

CopyOnWriteArrayList 我们看名字就知道,在写操作时,进行复制。在复制的副本中进行操作,然后再替换原来的数据,这样就不会阻碍读操作了。上面源码中也是,先加锁,防止复制多个副本,然后操作副本,然后写回原处。
从计算机的角度来看:复制旧内存块,改写新内存,然后指针指向新内存,回收就内存。

三、ConcurrentLinkedQueue

ConcurrentLinkedQueue是非阻塞队列,主要使用 CAS 非阻塞算法来实现线程安全。
从名字可以看出,ConcurrentLinkedQueue使用链表作为其数据结构,ConcurrentLinkedQueue 应该算是在高并发环境中性能最好的队列了。
这里不作过多的解读了,后续有时间专门出一篇源码总结。

四、BlockingQueue

BlockingQueue是阻塞队列。 BlockingQueue 是一个先进先出的队列(Queue),为什么说是阻塞(Blocking)的呢?是因为 BlockingQueue 支持当获取队列元素但是队列为空时,会阻塞等待队列中有元素再返回;也支持添加元素时,如果队列已满,那么等到队列可以放入新元素时再放入。
BlockingQueue 在生产者-消费者的场景中,是支持多消费者和多生产者的,说的其实就是线程安全问题。
BlockingQueue常用的实现类有:ArrayBlockingQueue、LinkedBlockingQueue 、PriorityBlockingQueue 。

ArrayBlockingQueue 一旦创建,容量不能改变。其并发控制采用可重入锁 ReentrantLock,不管是插入操作还是读取操作,都需要获取到锁才能进行操作。当队列容量满时,尝试将元素放入队列将导致操作阻塞;尝试从一个空队列中取一个元素也会同样阻塞。
ArrayBlockingQueue 默认情况下不能保证线程访问队列的公平性,所谓公平性是指严格按照线程等待的绝对时间顺序,即最先等待的线程能够最先访问到 ArrayBlockingQueue。而非公平性则是指访问 ArrayBlockingQueue 的顺序不是遵守严格的时间顺序,有可能存在,当 ArrayBlockingQueue 可以被访问时,长时间阻塞的线程依然无法访问到ArrayBlockingQueue。

若想保证公平性,采用代码如下:

private static ArrayBlockingQueue<Integer> blockingQueue = new ArrayBlockingQueue<Integer>(10,true);

LinkedBlockingQueue 底层基于单向链表实现的阻塞队列,可以当做无界队列也可以当做有界队列来使用,同样满足 FIFO 的特性,与 ArrayBlockingQueue 相比起来具有更高的吞吐量,为了防止 LinkedBlockingQueue 容量迅速增,损耗大量内存。通常在创建 LinkedBlockingQueue 对象时,会指定其大小,如果未指定,容量等于 Integer.MAX_VALUE 。

PriorityBlockingQueue 是一个支持优先级的无界阻塞队列。默认情况下元素采用自然顺序进行排序,也可以通过自定义类实现 compareTo() 方法来指定元素排序规则,或者初始化时通过构造器参数 Comparator 来指定排序规则。
PriorityBlockingQueue 并发控制采用的是可重入锁 ReentrantLock,队列为无界队列(ArrayBlockingQueue 是有界队列LinkedBlockingQueue 也可以通过在构造函数中传入 capacity 指定队列最大的容量,但是 PriorityBlockingQueue 只能指定初始的队列大小,后面插入元素的时候,如果空间不够的话会自动扩容)。

五、ConcurrentSkipListMap

ConcurrentSkipListMap表示使用跳表实现map。跳表是什么呢,看下图(图片引用:https://javaguide.cn/java/concurrent/java-concurrent-collections.html#priorityblockingqueue):
在这里插入图片描述
跳表的本质是同时维护了多个链表,并且链表是分层的,最底层是所有元素的链表,每上面一层链表都是下面一层的子集。跳表内的所有链表的元素都是排序的。查找时,可以从顶级链表开始找。一旦发现被查找的元素大于当前链表中的取值,就会转入下一层链表继续找。这也就是说在查找过程中,搜索是跳跃式的。
如果查18的话,本来要查18次,现在只需要查1,7,13,13,17,17,18这7个就行了。
跳表是一种利用空间换时间的算法。
使用跳表实现 Map 和使用哈希算法实现 Map 的另外一个不同之处是:哈希并不会保存元素的顺序,而跳表内所有的元素都是排序的。因此在对跳表进行遍历时,你会得到一个有序的结果。
本文参考:
https://javaguide.cn/java/concurrent/java-concurrent-collections.html#concurrentskiplistmap

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/51037.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Linux基本命令(三)——服务器搭建

搭建简单Web服务器 安装web服务 yum -y install httpd 启动httpd服务 systemctl start httpd查看httpd是否开启成功 service httpd status以下是状态信息&#xff1a; 重新启动httpd systemctl restart httpd6.进入主配置文件 vim /etc/httpd/conf/httpd.conf编辑自配置文件 v…

FPGA控制W5500完成UDP环回测试

FPGA控制W5500完成UDP环回测试&#xff11; 前言&#xff12; 前期准备&#xff13; &#xff37;5500寄存器描述4 &#xff37;5500 环回测试4.1 W5500初始化4.1.1 通用寄存器初始化4.1.2 socket寄存器初始化4.2 W5500数据接收4.3 W5500数据发送4.4 数据环回5 总结&#x…

RKMEDIA--VO的使用

这一节主要说说rkmedia vo模块的使用。 rkmedia的vo是对DRM接口的封装&#xff0c;提供给用户更方便的使用&#xff0c;rv1126/rv1109支持两个vo图层。 1、首先先介绍一下DRM的测试命令--modetest&#xff0c;用来确认当前屏幕能够正常点亮。 modetest -M rockchip //打印出…

融云艾瑞发布《政企数智办公平台行业研究报告》,解读数智化时代的办公新趋势

关注公众号文章扫码报名融云&艾瑞“政企数智办公报告及新品发布会” 近期&#xff0c;安全可信的通信云服务商融云&#xff0c;携手业内权威研究机构艾瑞咨询联合发布《2022 年中国政企数智办公平台行业研究报告》&#xff08;下简称《报告》&#xff09;&#xff0c;回顾政…

Kotlin高仿微信-第28篇-朋友圈-预览图片、预览小视频

Kotlin高仿微信-项目实践58篇详细讲解了各个功能点&#xff0c;包括&#xff1a;注册、登录、主页、单聊(文本、表情、语音、图片、小视频、视频通话、语音通话、红包、转账)、群聊、个人信息、朋友圈、支付服务、扫一扫、搜索好友、添加好友、开通VIP等众多功能。 Kotlin高仿…

ios照片误删怎么恢复,iphone已经删除的照片怎么恢复

苹果手机里面的重要照片被删除了&#xff0c;相信很多人都比较着急&#xff0c;想要想办法找回来。ios照片误删怎么恢复&#xff1f; 方法1.通过“最近删除”恢复照片 苹果删除的照片如何恢复&#xff1f;一般情况下&#xff0c;从苹果手机刚删除的照片会暂存在“最近删除”这…

使用MAT分析线上问题实战

概述 MAT&#xff0c;下载地址&#xff0c;Eclipse Memory Analysis Tools&#xff0c;一个分析Java堆数据的专业工具&#xff0c;可以计算出内存中对象的实例数量、占用空间大小、引用关系等&#xff0c;可得知哪些线程阻止垃圾收集器的回收工作&#xff0c;从而定位内存泄漏…

如何低成本减少企业知识流失?天翎知识文档系统+群晖NAS值得一试

编者按&#xff1a;知识管理可以减少企业知识流失&#xff0c;有效提高企业员工工作水平&#xff0c;增强企业综合竞争力。如何小成本做好企业知识管理呢&#xff1f;天翎知识文档系统群晖NAS值得一试。 关键词&#xff1a;标签分类&#xff0c;权限管理&#xff0c;在线预览&…

Git学习

Git是什么 Github作为最大的代码托管平台&#xff0c;是基于Git开发的 Git是最优秀的版本控制工具 iCode是基于Git的代码托管平台 版本控制&#xff1a;是对软件开发过程中各种程序代码&#xff0c;配置文件&#xff0c;说明文档等。 版本控制系统&#xff1a;集中式、分布式 …

在Mac中管理多版本 java——安装和使用 jenv

jenv 的 github 地址:https://github.com/jenv/jenv 安装 $ brew install jenv安装成功后需要进行一下简单的配置,让它可以起作用 使用Bash的情况$ echo export PATH="$HOME/.jenv/bin:$PATH" >> ~/.bash_profile $ echo eval "$(jenv init -)" &…

MAC 搭建vue开发环境,配置环境变量

1.官网下载nodejs安装包 http://nodejs.p2hp.com/ 下载完成后安装&#xff0c;一直点击下一步即可 2.自定以配置全局模块路径和缓存路径 先自己找一个路径创建两个文件夹&#xff0c;node_cache 和 node_global 打开终端&#xff0c;执行一下俩条命令,注意引号中的路径要换…

图纸识别自动生成BOM清单的方法

01 方案应用领域及行业 高端装备制造业行业、离散型制造业、电气机械和器材制造业等。 02 方案应用场景 某特变电工公司是国内输变电行业的核心骨干企业&#xff0c;每年生产产能巨大&#xff0c;拥有海量的技术图纸&#xff0c;因此技术人员人工拆解设计图纸的工作难度系数大…

【优化调度】基于改进遗传算法的公交车调度排班优化的研究与实现(Matlab代码实现)

目录 1 概述 2 运行结果 3 参考文献 4 Matlab代码 1 概述 本文对当前公交企业调度系统进行了分析&#xff0c;建立了公交排班的数学模型。本文基于数据挖掘分析的结果上&#xff0c;使用截面客流量数据对模型进行约束&#xff0c;得出了公交客流出行的空间分布规律。再以…

软件测试1

这里写自定义目录标题软件测试的定义1、软件测试的目的2、软件测试的要求3、测试与开发的模型3.1 测试的工作流程3.2 开发模型3.2.1 瀑布模型3.2.2 增量模型3.2.3 快速模型3.2.4 其他模型3.3 测试模型4、测试与开发的关系5、软件测试分类软件测试的定义 找Bug,发现缺陷。使用人…

全球科学家给孩子的stem课【001-046】mp3合集

全球科学家给孩子的stem课【001-046】mp3合集&#xff0c;适合给孩子们启蒙教育使用。 一只蚂蚁走丢后的8种可能结局.mp3 下雨天清爽的味道&#xff0c;来自尸体和臭气.mp3 为什么光的三原色是红绿蓝&#xff0c;绘画的三原色又成了红黄蓝&#xff1f;.mp3 为什么剖腹产的孩子…

患有癌症的心力衰竭患者LVAD植入前景可期

相关调查显示&#xff0c;患有终末期心力衰竭的癌症患者&#xff08;有癌症史&#xff09;正在增加&#xff0c;但其进行心脏移植的可能性不大&#xff0c;而左心室辅助装置&#xff08;LVAD&#xff09;是一种可选择的替代策略。近日&#xff0c;发表于Circulation: Heart Fai…

[附源码]SSM计算机毕业设计疫情期间回乡人员管理系统JAVA

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

Kotlin高仿微信-第27篇-朋友圈-相册选择图片或小视频

Kotlin高仿微信-项目实践58篇详细讲解了各个功能点&#xff0c;包括&#xff1a;注册、登录、主页、单聊(文本、表情、语音、图片、小视频、视频通话、语音通话、红包、转账)、群聊、个人信息、朋友圈、支付服务、扫一扫、搜索好友、添加好友、开通VIP等众多功能。 Kotlin高仿…

ContentProvider启动流程分析

文章目录1.ActivityThread.handleBindApplication()2.ActivityThread.installContentProviders()3.ActivityThread.installProvider()4.AppComponentFactory.instantiateProvider()5.ActivityManagerService.publishContentProviders()6.ContentProviderHelper.publishContentP…

基于Web的美食分享平台的设计与实现——HTML+CSS+JavaScript水果介绍网页设计(橙子之家)

&#x1f468;‍&#x1f393;静态网站的编写主要是用HTML DIVCSS JS等来完成页面的排版设计&#x1f469;‍&#x1f393;,常用的网页设计软件有Dreamweaver、EditPlus、HBuilderX、VScode 、Webstorm、Animate等等&#xff0c;用的最多的还是DW&#xff0c;当然不同软件写出的…