【Java多线程】6——集合线程安全

6 集合线程安全

⭐⭐⭐⭐⭐⭐
Github主页👉https://github.com/A-BigTree
笔记仓库👉https://github.com/A-BigTree/tree-learning-notes
个人主页👉https://www.abigtree.top
⭐⭐⭐⭐⭐⭐


如果可以,麻烦各位看官顺手点个star~😊

如果文章对你有所帮助,可以点赞👍收藏⭐支持一下博主~😆


文章目录

  • 6 集合线程安全
    • 6.1 List集合
      • 6.1.1 使用`ArrayList`
      • 6.1.2 各种方案比较
      • 6.1.3 写时复制技术
        • 初始状态
        • 写操作
        • 写操作完成
    • 6.2 Set集合
    • 6.3 Map集合
      • 6.3.1 `ConcurrentHashMap`
      • 6.3.2 锁分段技术

6.1 List集合

6.1.1 使用ArrayList

// 创建被测试的List集合对象
// 具体集合类型ArrayList:抛出java.util.ConcurrentModificationException异常
List<String> list = new ArrayList<>();// 在多个线程中对这个List集合执行读写操作
for (int i = 0; i < 5; i++) {new Thread(()->{for (int j = 0; j < 3; j++) {// 向集合对象写入数据list.add(UUID.randomUUID().toString().replace("-","").substring(0, 5));// 打印集合对象,等于是读取数据System.out.println(list);}},"thread"+i).start();}

6.1.2 各种方案比较

// 创建被测试的List集合对象
// 具体集合类型ArrayList:抛出java.util.ConcurrentModificationException异常// 具体集合类型Vector:不会抛异常,线程安全,但是这个类太古老// Collections.synchronizedList(new ArrayList<>()):不会抛异常,但是锁定范围大,性能低
// public void add(int index, E element) { synchronized (mutex) {list.add(index, element);} }
// public E get(int index) { synchronized (mutex) {return list.get(index);} }// 具体集合类型CopyOnWriteArrayList:使用了写时复制技术,兼顾了线程安全和并发性能
List<String> list = new CopyOnWriteArrayList<>();

6.1.3 写时复制技术

初始状态

在这里插入图片描述

写操作

在这里插入图片描述

写操作完成

在这里插入图片描述

  • 使用写时复制技术要向集合对象中写入数据时:先把整个集合数组复制一份

  • 将新数据写入复制得到的新集合数组

  • 再让指向集合数组的变量指向新复制的集合数组

优缺点:

  • 优点:写操作还是要加独占锁,这方面没区别;读操作允许并发执行,效率提升。
  • 缺点:由于需要把集合对象整体复制一份,所以对内存的消耗很大

对应类中的源代码:

  • 所在类:java.util.concurrent.CopyOnWriteArrayList
    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();}}

6.2 Set集合

采用了写时复制技术的Set集合:java.util.concurrent.CopyOnWriteArraySet

// 1、创建集合对象
Set<String> set = new CopyOnWriteArraySet<>();// 2、创建多个线程,每个线程中读写 List 集合
for (int i = 0; i < 5; i++) {new Thread(()->{for (int j = 0; j < 5; j++) {// 写操作:随机生成字符串存入集合set.add(UUID.randomUUID().toString().replace("-","").substring(0, 5));// 读操作:打印集合整体System.out.println("set = " + set);}}, "thread-"+i).start();}

对应类中源码:

  • 所在类:java.util.concurrent.CopyOnWriteArraySet
    public boolean add(E e) {return al.addIfAbsent(e);}
  • 所在类:java.util.concurrent.CopyOnWriteArrayList
    private boolean addIfAbsent(E e, Object[] snapshot) {final ReentrantLock lock = this.lock;lock.lock();try {Object[] current = getArray();int len = current.length;if (snapshot != current) {// Optimize for lost race to another addXXX operationint common = Math.min(snapshot.length, len);for (int i = 0; i < common; i++)if (current[i] != snapshot[i] && eq(e, current[i]))return false;if (indexOf(e, current, common, len) >= 0)return false;}Object[] newElements = Arrays.copyOf(current, len + 1);newElements[len] = e;setArray(newElements);return true;} finally {lock.unlock();}}

6.3 Map集合

6.3.1 ConcurrentHashMap

全类名:java.util.concurrent.ConcurrentHashMap

测试代码:

// 1、创建集合对象
Map<String, String> map = new ConcurrentHashMap<>();// 2、创建多个线程执行读写操作
for (int i = 0; i < 5; i++) {new Thread(()->{for (int j = 0; j < 5; j++) {String key = UUID.randomUUID().toString().replace("-","").substring(0, 5);String value = UUID.randomUUID().toString().replace("-","").substring(0, 5);map.put(key, value);System.out.println("map = " + map);}}, "thread" + i).start();
}

6.3.2 锁分段技术

在这里插入图片描述

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

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

相关文章

FPGA + 图像处理 (二) RGB转YUV色域、转灰度图及仿真

前言 具体关于色域的知识就不细说了&#xff0c;简单来讲YUV中Y通道可以理解为就是图像的灰度图&#xff0c;因此&#xff0c;将RGB转化为YUV是求彩色图的灰度直方图、进行二值化操作等的基础。 HDMI时序生成模块 这里先介绍一下仿真时用于生成HDMI时序&#xff0c;用这个时…

Rust---有关介绍

目录 Rust---有关介绍变量的操作Rust 数值库&#xff1a;num某些基础数据类型序列(Range)字符类型单元类型 发散函数表达式&#xff08;&#xff01; 语句&#xff09; Rust—有关介绍 得益于各种零开销抽象、深入到底层的优化潜力、优质的标准库和第三方库实现&#xff0c;Ru…

汽车贴膜改色小程序源码 汽车配色小程序源码 车身改色app源码 带后台 带数据

汽车贴膜改色小程序源码 车身改色app源码 汽车配色小程序源码 带后台 带数据 整站源码&#xff0c;包含完整前端小程序&#xff0c;后台源码&#xff0c;数据库数据。 直接部署&#xff0c;就能使用&#xff0c;源码素材远程开发&#xff0c;可以定制开发。 全开源&#xff0c;…

算法学习——LeetCode力扣图论篇1(797. 所有可能的路径、200. 岛屿数量、695. 岛屿的最大面积)

算法学习——LeetCode力扣图论篇1 797. 所有可能的路径 797. 所有可能的路径 - 力扣&#xff08;LeetCode&#xff09; 描述 给你一个有 n 个节点的 有向无环图&#xff08;DAG&#xff09;&#xff0c;请你找出所有从节点 0 到节点 n-1 的路径并输出&#xff08;不要求按特…

数据结构(初阶)第二节:顺序表

从本文正式进入对数据结构的讲解&#xff0c;开始前友友们要有C语言的基础&#xff0c;熟练掌握动态内存管理、结构体、指针等章节&#xff0c;方便后续的学习。 顺序表&#xff08;Sequence List&#xff09; 线性表的概念&#xff1a;线性表&#xff08;linear list&#xff…

数据结构进阶篇 之 【插入排序】详细讲解(直接插入排序,希尔排序)

千万不要因为一件事不会做而失去信心&#xff0c;你又不是只有这一件事不会&#xff0c;你还有很多呢 一、插入排序 1.直接插入排序 InsertSort 1.1 基本思想 1.2 实现原理 1.3 代码实现 1.4 直接插入排序的特性总结 2.希尔排序 ShellSort 2.1 基本思想 2.2 实现原理 …

Docker命令及部署Java项目

文章目录 简介Docker镜像镜像列表查找镜像拉取镜像删除镜像镜像标签 Docker容器容器启动容器查看容器停止和重启后台模式和进入强制停止容器清理停止的容器容器错误日志容器别名及操作 Docker部署Java项目 简介 Docker是一种容器化技术&#xff0c;可以帮助开发者轻松打包应用…

什么是AIGC,AIGC的应用领域有哪些,以及对AIGC的未来展望有什么值得关注的方向

AIGC:人工智能生成内容的深度解析 在数字技术的浪潮中,AIGC(ArtificialIntelligenceGeneratedContent,人工智能生成内容)逐渐崭露头角,成为继专业生产内容(PGC)和用户生产内容(UGC)之后的新型内容创作方式。它不仅改变了内容生产的传统模式,更在多个行业中展现出…

【原创】基于springboot+vue学生信息管理系统设计与实现

个人主页&#xff1a;程序猿小小杨 个人简介&#xff1a;从事开发多年&#xff0c;Java、Php、Python、前端开发均有涉猎 博客内容&#xff1a;Java项目实战、项目演示、技术分享 文末有作者名片&#xff0c;希望和大家一起共同进步&#xff0c;你只管努力&#xff0c;剩下的交…

国资委确定首批起航企业,重点布局人工智能、量子信息等新兴领域

国务院国资委近日按照“四新”&#xff08;新赛道、新技术、新平台、新机制&#xff09;标准&#xff0c;遴选确定了首批启航企业&#xff0c;加快新领域新赛道布局、培育发展新质生产力。 据了解&#xff0c;去年以来&#xff0c;国务院国资委围绕加快培育创新型国有企业&…

手机销量分析案例

项目背景 某电商商城随着业务量的发展&#xff0c;积累了大量的用户手机销售订单数据。决策层希望能够通过对这些数据的分析了解更多的用户信息及用户的分布&#xff0c;从而可以指导下一年的市场营销方案以及更加精准的定位市场&#xff0c;进行广告投放。 数据说明 数据时…

YARN集群 和 MapReduce 原理及应用

YARN集群模式 本文内容需要基于 Hadoop 集群搭建完成的基础上来实现 如果没有搭建&#xff0c;请先按上一篇: <Linux 系统 CentOS7 上搭建 Hadoop HDFS集群详细步骤> 搭建&#xff1a;https://mp.weixin.qq.com/s/zPYsUexHKsdFax2XeyRdnA 配置hadoop安装目录下的 etc…

【JavaEE初阶系列】——多线程案例三——定时器

目录 &#x1f6a9;定时器是什么 &#x1f6a9;标准库中的定时器 &#x1f6a9;自定义定时器 &#x1f388;构造Task类 &#x1f4dd;相对时间和绝对时间 &#x1f388;构造MyTime类 &#x1f4dd;队列空和队列不为空 &#x1f4dd;wait(带参)解决消耗资源问题 &#…

CentOS7安装Flink1.17伪分布式

前提条件 拥有1台CentOS7 CentOS7安装好jdk&#xff0c;官方文档要求java 11&#xff0c;使用java 8也可以。可参考 CentOS7安装jdk8 下载安装包 下载安装包 [hadoopnode1 ~]$ cd installfile/ [hadoopnode1 installfile]$ wget https://archive.apache.org/dist/flink/flin…

4款在线网页原型图设计软件推荐

与桌面端相比&#xff0c;在线网页原型设计软件的使用具有优势&#xff0c;因为在线网页原型设计软件在整个使用过程中不需要安装&#xff0c;在线网页原型设计软件在任何地方都没有限制。更重要的是&#xff0c;无论是现在使用的 Linux&#xff0c;在线网页原型设计软件在操作…

SV学习笔记(一)

SV&#xff1a;SystemVerilog 开启SV之路 数据类型 內建数据类型 四状态与双状态 &#xff1a; 四状态指0、1、X、Z&#xff0c;包括logic、integer、 reg、 wire。双状态指0、1&#xff0c;包括bit、byte、 shortint、int、longint。 有符号与无符号 &#xff1a; 有符号&am…

使用 FinalShell 进行远程连接(ssh 远程连接 Linux 服务器)

目录 前言 基本使用教程 新建远程连接 连接主机 自定义命令 路由追踪 前言 后端开发&#xff0c;必然需要和服务器打交道&#xff0c;部署应用&#xff0c;排查问题&#xff0c;查看运行日志等等。一般服务器都是集中部署在机房中&#xff0c;也有一些直接是云服务器&am…

UGUI 进阶

UI事件监听接口 目前所有的控件都只提供了常用的事件监听列表 如果想做一些类似长按&#xff0c;双击&#xff0c;拖拽等功能是无法制作的 或者想让Image和Text&#xff0c;RawImage三大基础控件能够响应玩家输入也是无法制作的 而事件接口就是用来处理类似问题 让所有控件都…

【MySQL系列】使用 ALTER TABLE 语句修改表结构的方法

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

图的应用试题

01&#xff0e;任何一个无向连通图的最小生成树( )。 A.有一棵或多棵 B.只有一棵 C.一定有多棵 D.可能不存在 02.用Prim算法和Kruskal算法构造图的最小生成树&#xff0c;…