并发容器+并发队列【ConcurentHashMap、CopyOnWriteArrayList、阻塞队列、ArrayBlockingQueue】

并发容器

  • 什么是并发容器?
    • 同步容器:
    • 并发容器:
  • ConcurrentHashMap
    • 结构图
      • JDK1.7结构图
      • JDK1.8结构图
  • CopyOnWriteArrayList
    • 实现原理
  • 并发队列
    • 阻塞队列
    • ArrayBlockingQueue

转自极客时间

什么是并发容器?

在JUC包中,有一大部分是关于并发容器的,如ConcurrentHashMap,ConcurrentSkipListMap, CopyOnWriteArrayList及阻塞队列。这里将介绍使用频率、面试中出现频繁的最高的 ConcurrentHashMap和阻塞队列。

注意:这里说到的容器概念,相当于我们理解中的集合的概念。

同步容器:

Java中的集合主要分为四大类:List、Map、Set和Queue,但是并不是所有集合都是线程安全的。比 如,我们经常使用的ArrayList,HashMap,HashSet就不是线程安全的。
早期的JDK1.0中的就提供了线程安全的集合,包括Vector,Stack和Hashtable。此外还有在JDK1.2中增 加的Collections中内部SynchronizedXxx类,它们也是线程安全的集合,可以由对应 Collections.synchronizedXxx工厂方法创建。这些类实现线程安全的方式都是一样的:都是基于 synchronized这个同步关键字实现的,对每个公有方法都进行了同步,保证每次只有一个线程能访问集 合,所以它们被称为线程安全的集合(同步容器)。

并发容器:

在JDK1.5之前,JDK提供的线程安全的类都是同步集合容器。同步容器都是线程安全的,但是所有线程 对容器只能串行访问,性能很差。在JDK1.5之后引入的JUC并发包,提供的更多类型的并发容器,在性 能上做了很多改进优化,可以用来替代同步容器。它们都是针对多线程并发访问来进行设计的,我们称 它们为并发容器。
并发容器依然可以归属到我们提到的四大类:List、Map、Set 和 Queue。

在这里插入图片描述
这里我总结了一下它们特性和使用场景:

  1. List容器:
    Vector: 使用synchronized同步锁,数据具有强一致性。适合于对数据有强一致性要求的场 景,但性能较差。
    CopyOnWriteArrayList: 底层使用数组存储数据,使用复制副本实现有锁写操作,不能保 证强一致性。适合于读多写少,允许读写数据短暂不一致的高并发场景。

  2. Map容器
    Hashtable: 使用synchronized同步锁,数据具有强一致性。适合于对数据有强一致性要求的 场景,但性能较差。
    ConcurrentHashMap: 基于数组+链表+红黑树实现,写操作时通过synchronized同步锁将 HashEntry作为锁的粒度支持一定程度的并发写,具有弱一致性。适合于存储数据量较小,读 多写少且不要求强一致性的高并发场景。
    ConcurrentSkipListMap: 基于跳表实现的有序Map,使用CAS实现无锁化读写,具有弱一致 性。适合于存储数据量大,读写都比较频繁,对数据不要求强一致性的高并发场景。

  3. Set容器
    CopyOnWriteArraySet: 底层使用数组存储数据,使用复制副本实现有锁写操作,不能保证 强一致性。适合于读多写少,允许读写数据短暂不一致的场景。 ConcurrentSkipListSet: 基于跳表实现的有序Set,使用CAS实现无锁化读写,具有弱一致 性。适合于存储数据量大,读写都 比较频繁,对数据不要求强一致性的高并发场景。

ConcurrentHashMap

结构图

JDK1.7结构图

Java7中的ConcurrentHashMap最外层是多个segment,每个segment的底层数据结构与HashMap类 似,仍然是数组和链表组成。
每个segment独立上ReentrantLock锁,每个segment之间互不影响,提高并发效率。
默认有16个segment,最多可以同时支持16个线程并发写(操作分别分布在不同的Segment上)。这个 默认值可以在初始化时设置,但一旦初始化以后,就不可以再扩容了。

在这里插入图片描述

JDK1.8结构图

ConcurrentHashMap是一个存储 key/value 对的容器,并且是线程安全的。
改进一: 取消segments字段,直接采用transient volatile HashEntry<K,V>[] table保存数据,采用 table数组元素作为锁,从而实现了对每一行数据进行加锁,进一步减少并发冲突的概率。
改进二: 将原先table数组+单向链表的数据结构,变更为table数组+单向链表+红黑树的结构。查询 更快

在这里插入图片描述
在这里插入图片描述

CopyOnWriteArrayList

实现原理

CopyOnWrite 思想:是平时查询的时候,都不需要加锁,随便访问,只有在更新的时候,才会从原来的 数据复制一个副本出来,然后修改这个副本,最后把原数据替换成当前的副本。修改操作的同时,读操 作不会被阻塞,而是继续读取旧的数据。这点要跟读写锁区分一下。

public class Demo15CopyOnWriteArrayList {public static void main(String[] args) {//1、初始化CopyOnWriteArrayListList<Integer> tempList = Arrays.asList(new Integer [] {1,2});CopyOnWriteArrayList<Integer> copyList = new CopyOnWriteArrayList<>(tempList);ThreadLocal tl = new ThreadLocal();//2、模拟多线程对list进行读和写ExecutorService executorService = Executors.newFixedThreadPool(10);executorService.execute(new ReadThread(copyList));executorService.execute(new WriteThread(copyList));executorService.execute(new WriteThread(copyList));executorService.execute(new WriteThread(copyList));executorService.execute(new ReadThread(copyList));executorService.execute(new WriteThread(copyList));executorService.execute(new ReadThread(copyList));executorService.execute(new WriteThread(copyList));try {TimeUnit.SECONDS.sleep(5);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}System.out.println("copyList size:"+copyList.size());executorService.shutdown();}
}class ReadThread implements Runnable {private List<Integer> list;public ReadThread(List<Integer> list) {this.list = list;}@Overridepublic void run() {System.out.print("size:="+list.size()+",::");for (Integer ele : list) {System.out.print(ele + ",");}System.out.println();}
}class WriteThread implements Runnable {private List<Integer> list;public WriteThread(List<Integer> list) {this.list = list;}@Overridepublic void run() {this.list.add(9);}
}

在这里插入图片描述

并发队列

在这里插入图片描述
在这里插入图片描述

阻塞队列

在这里插入图片描述

ArrayBlockingQueue

有界,可以指定容量
公平:可以指定是否需要保证公平,如果想要保证公平,则等待最长时间的线程会被优先处理,不过会带来一定的性能损耗。
场景:有10个面试者,只有1个面试官,大厅有3个位子让面试者休息,每个人面试时间10秒,模拟所有 人面试的场景。

/*** 案例:有10个面试者,只有1个面试官,大厅有3个位子让面试者休息,每个人面试时间10秒,模拟所有人面试的场景。*/
public class Demo16ArrayBlockingQueue {static ArrayBlockingQueue<String> queue = new ArrayBlockingQueue<String>(3);public static void main(String[] args) {Interviewer r1 = new Interviewer(queue);//面试官Engineers e2 = new Engineers(queue);//程序员们new Thread(r1).start();new Thread(e2).start();}
}class Interviewer implements Runnable {BlockingQueue<String> queue;public Interviewer(BlockingQueue queue) {this.queue = queue;}@Overridepublic void run() {System.out.println("面试官:我准备好了,可以开始面试");String msg;try {while(!(msg = queue.take()).equals("stop")){System.out.println(msg + " 面试+开始...");TimeUnit.SECONDS.sleep(10);//面试10sSystem.out.println(msg + " 面试-结束...");}System.out.println("所有候选人都结束了");} catch (InterruptedException e) {e.printStackTrace();}}
}class Engineers implements Runnable {BlockingQueue<String> queue;public Engineers(BlockingQueue queue) {this.queue = queue;}@Overridepublic void run() {for (int i = 1; i <= 10; i++) {String candidate = "程序员" + i;try {queue.put(candidate);System.out.println(candidate+" 就坐=等待面试~");} catch (InterruptedException e) {e.printStackTrace();}}try {queue.put("stop");} catch (InterruptedException e) {e.printStackTrace();}}
}

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

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

相关文章

【Python中Selenium元素定位的各种方法】

1、元素定位操作&#xff1a; 2、创建浏览器驱动操作&#xff0c;导入By模块&#xff1a; from selenium import webdriver # 用于界面与浏览器互动 from selenium.webdriver.common.by import By # 用于元素定位 driver webdriver.Chrome() # 调用Chrome类&#xff0c;创…

材料非线性Matlab有限元编程:初应力法与初应变法

导读:本文主要围绕材料非线性问题的有限元Matlab编程求解进行介绍,重点围绕牛顿-拉普森法(切线刚度法)、初应力法、初应变法等三种非线性迭代方法的算法原理展开讲解,最后利用Matlab对材料非线性问题有限元迭代求解算法进行实现,展示了实现求解的核心代码。这些内容都将收…

2023年总结

人们总说时间会改变一切&#xff0c;但事实上你得自己来。 今年开始给自己的时间读书、工作、生活都加上一个2.0的release版本号&#xff0c;相比过去的一年还是有很多进步的。 就跟git commit一样&#xff0c;一步一步提交优化&#xff0c;年底了发个版本。用李笑来的话说&am…

【洛谷题解】P1595 信封问题

题目链接&#xff1a;信封问题 - 洛谷 题目难度&#xff1a;普及- 涉及知识点&#xff1a;错排 题意&#xff1a; 分析&#xff1a;直接用错排公式代入即可 AC代码推理公式&#xff1a; #include<bits/stdc.h> using namespace std; long long f[25]; int main()//用…

服务器被黑,安装Linux RootKit木马

前言 疫情还没有结束&#xff0c;放假只能猫家里继续分析和研究最新的攻击技术和样本了&#xff0c;正好前段时间群里有人说服务器被黑&#xff0c;然后扔了个样本在群里&#xff0c;今天咱就拿这个样本开刀&#xff0c;给大家研究一下这个样本究竟是个啥&#xff0c;顺便也给…

《MySQL 简易速速上手小册》第10章:未来趋势和进阶资源(2024 最新版)

文章目录 10.1 MySQL 在云计算和容器化中的应用10.1.1 基础知识10.1.2 重点案例&#xff1a;使用 Python 部署 MySQL 到 Kubernetes10.1.3 拓展案例 1&#xff1a;在 AWS RDS 上部署 MySQL 实例10.1.4 拓展案例 2&#xff1a;使用 Docker 部署 MySQL 10.2 MySQL 和 NoSQL 的整合…

基于图像掩膜和深度学习的花生豆分拣(附源码)

目录 项目介绍 图像分类网络构建 处理花生豆图片完成预测 项目介绍 这是一个使用图像掩膜技术和深度学习技术实现的一个花生豆分拣系统 我们有大量的花生豆图片&#xff0c;并以及打好了标签&#xff0c;可以看一下目录结构和几张具体的图片 同时我们也有几张大的图片&…

基于片段的3D分子生成扩散模型 - AutoFragDiff 评测

AutoFragDiff 是一个基于片段的&#xff0c;自回归的&#xff0c;口袋条件下的&#xff0c;3D分子生成扩散模型。 AutoFragDiff方法来源于文章《Autoregressive fragment-based diffusion for pocket-aware ligand design》&#xff0c;由加州大学的Mahdi Ghorbani等人于2023年…

【Java EE初阶十一】文件操作(IO)

1. 认识文件 所谓的文件是一个广义的概念&#xff0c;可以代表很多东西&#xff1b;在操作系统里面&#xff0c;会把很多的硬件设备和软件设备都抽象成“文件”&#xff0c;统一进行管理&#xff1b;但是大部分情况下&#xff0c;我们读到的文件&#xff0c;都是指硬盘的文件&a…

MYSQL笔记:约束条件

MYSQL笔记&#xff1a;约束条件 主键约束 不能为空&#xff0c;值必须是不同的&#xff08;唯一性&#xff09; 一个表只能修饰一个主键 PRIMARY KEY自增约束 AUTO_INCREMENT唯一键约束 可以为空 unique非空约束 not null 默认值约束 default 外键约束 foreign key …

CMD常用命令

目录 1.简介 2.基本功能 3.打开方式 4.常用命令 5.练习——通过CMD打开QQ 1.简介 CMD&#xff08;Command Prompt&#xff09;是Windows操作系统中的命令行界面工具&#xff0c;它允许用户通过键入文本命令来与操作系统进行交互。CMD提供了一种不依赖图形用户界面的方式来…

详解格式化输入函数scanf

大家好&#xff0c;今天给大家介绍详解格式化输入函数scanf&#xff0c;文章末尾附有分享大家一个资料包&#xff0c;差不多150多G。里面学习内容、面经、项目都比较新也比较全&#xff01;可进群免费领取。 C语言中常用的输入可以有多种方式&#xff0c;如scanf(),getchar(),g…

centos中docker操作

一、安装docker 确保系统是CentOS 7并且内核版本高于3.10,可以通过uname -r命令查看内核版本。 更新系统软件包到最新版本,可以使用命令yum update -y。 安装必要的软件包,包括yum-utils、device-mapper-persistent-data和lvm2。使用命令yum install -y yum-utils devic…

Mysql制作数据表

一.注意&#xff1a; 1.&#xff08;Mysql尽量用大写&#xff0c; 2.结尾为‘&#xff1b;’&#xff0c; 3.‘’与“”效果一样&#xff0c; 4.数据表名称显示时定为小写&#xff0c; 5.很多人教的时候喜欢用英文&#xff0c;我觉得麻烦&#xff0c;于是我用中文举例&…

moduleID的使用

整个平台上有很多相同的功能&#xff0c;但是需要不同的内容。例如各个模块自己的首页上有滚动新闻、有友好链接等等。为了公用这些功能&#xff0c;平台引入了moduleID的解决方案。 在前端的配置文件中&#xff0c;配置了模块号&#xff1a; 前端页面请求滚动新闻时&#xff0…

微软AD域替代方案,助力企业摆脱hw期间被攻击的窘境

在红蓝攻防演练&#xff08;hw行动&#xff09;中&#xff0c;AD域若被攻击成功&#xff0c;是其中一个扣分最多的一项内容。每年&#xff0c;宁盾都会接到大量AD在hw期间被攻击&#xff0c;甚至是被打穿的企业客户。过去&#xff0c;企业还会借助2FA双因子认证加强OA、Exchang…

ChatGPT高效提问—prompt常见用法(续篇七)

ChatGPT高效提问—prompt常见用法&#xff08;续篇七&#xff09; 1.1 零样本、单样本和多样本 ​ ChatGPT拥有令人惊叹的功能和能力&#xff0c;允许用户自由向其提问&#xff0c;无须提供任何具体的示例样本&#xff0c;就可以获得精准的回答。这种特性被称为零样本&#x…

每日一题——LeetCode1417.重新格式化字符串

方法一 个人方法&#xff1a; s里的字符只有小写字母和数字两种情况&#xff0c;我们可以把s里的字母和数字分隔成两个字符串&#xff0c; 比较两个字符串的长度&#xff0c;只有当两个字符串的长度差值的绝对值为1或0才能满足题意。 长度更长的要放在结果字符串的第一位&am…

嵌入式学习之Linux入门篇笔记——18,makefile基本语法(下)

配套视频学习链接&#xff1a;http://【【北京迅为】嵌入式学习之Linux入门篇】 https://www.bilibili.com/video/BV1M7411m7wT/?p4&share_sourcecopy_web&vd_sourcea0ef2c4953d33a9260910aaea45eaec8 1.wildcard 函数 格式&#xff1a;$&#xff08;wildcard PAT…

SQL如何实现数据表行转列、列转行?

SQL行转列、列转行可以帮助我们更方便地处理数据&#xff0c;生成需要的报表和结果集。本文将介绍在SQL中如何实现数据表地行转列、列转行操作&#xff0c;以及实际应用示例。 这里通过表下面三张表进行举例 SQL创建数据库和数据表 数据表示例数据分别如下&#xff1a; data_…