当前位置: 首页 > news >正文

【多线程进阶】线程安全的集合类

文章目录

  • 前言
  • 1. 多线程环境使用 ArrayList
  • 2. 多线程环境使用队列
  • 3. 多线程环境使用哈希表
    • 3.1 HashTable
    • 3.2 ConcurrentHashMap
  • 总结


前言

本文主要讲解 Java 线程安全的集合类, 在之前学习过的集合类中, 只有 Vector, Stack, HashTable, 是线程安全的, 因为在他们的关键方法中, 都使用了 synchronized 去实现, 而其他的集合类都不是线程安全的. 但在多线程开发下, 保证线程安全又必不可找, 因此我们无法避免使用线程安全的集合类.

关注收藏, 开始学习吧🧐


1. 多线程环境使用 ArrayList

多线程环境下使用 ArrayList 主要有以下三个方法:

1. 自己使用同步机制 (synchronized 或者 ReentrantLock)

俩个锁均在前面多线程章节, 做过很多相关的讨论了. 此处不再展开.

2. Collections.synchronizedList(new ArrayList);

ArrayList 本身是没有使用 synchronized, 但是 synchronizedList 是标准库提供的一个基于 synchronized 进行线程同步的 List. synchronizedList 的关键操作上都带有 synchronized. 如果你不想自己进行加锁, 就可以使用它.

3. 使用 CopyOnWriteArrayList

CopyOnWrite容器即写时复制的容器.

  • 当我们往一个容器添加元素的时候, 不直接往当前容器添加, 而是先将当前容器进行 Copy, 复制出一个新的容器, 然后新的容器里添加元素.
  • 添加完元素之后, 再将原容器的引用指向新的容器.

这样做的好处是我们可以对 CopyOnWrite 容器进行并发的读, 没有引入任何的加锁操作, 因为当前容器不会添加任何元素.

所以 CopyOnWrite 容器也是一种读写分离的思想,读和写不同的容器。

优点:

  • 在读多写少的场景下, 性能很高, 不需要加锁竞争.

缺点:

  • 占用内存较多.
  • 新写的数据不能被第一时间读取到.

2. 多线程环境使用队列

在多线程开发时需要用到队列时, 我们可以根据不同场景, 来使用以下四个队列.

  1. ArrayBlockingQueue 基于数组实现的阻塞队列
  2. LinkedBlockingQueue 基于链表实现的阻塞队列
  3. PriorityBlockingQueue 基于堆实现的带优先级的阻塞队列
  4. TransferQueue 最多只包含一个元素的阻塞队列

3. 多线程环境使用哈希表

HashMap 本身不是线程安全的. 在多线程环境下使用哈希表可以使用:

  • HashTable
  • ConcurrentHashMap

3.1 HashTable

只是简单的把关键方法加上了 synchronized 关键字.

public synchronized V put(K key, V value) {}
public synchronized V get(Object key) {}

这样相当于直接针对 Hashtable 对象本身加锁.

  • 如果多线程访问同一个 Hashtable 就会直接造成锁冲突.
  • size 属性也是通过 synchronized 来控制同步, 也是比较慢的.
  • 一旦触发扩容, 就由该线程完成整个扩容过程. 这个过程会涉及到大量的元素拷贝, 效率会非常低.
    在这里插入图片描述

3.2 ConcurrentHashMap

相比于 Hashtable 做出了一系列的改进和优化. 以 Java1.8 为例.

  • 读操作没有加锁(但是使用了 volatile 保证从内存读取结果), 只对写操作进行加锁. 加锁的方式仍然是是用 synchronized, 但是不是锁整个对象, 而是 “锁桶” (用每个链表的头结点作为锁对象), 大大降低了锁冲突的概率.
  • 充分利用 CAS 特性. 比如 size 属性通过 CAS 来更新. 避免出现重量级锁的情况.
  • 优化了扩容方式: 化整为零
    • 发现需要扩容的线程, 只需要创建一个新的数组, 同时只搬几个元素过去.
    • 扩容期间, 新老数组同时存在.
    • 后续每个来操作 ConcurrentHashMap 的线程, 都会参与搬家的过程. 每个操作负责搬运一小部分元素.
    • 搬完最后一个元素再把老数组删掉.
    • 这个期间, 插入只往新数组加.
    • 这个期间, 查找需要同时查新数组和老数组
      在这里插入图片描述

总结

✨ 本文重点讲了 Java 中一些线程安全的集合类, 在并发编程中时很有用的, 请大家熟悉.
✨ 想了解更多的多线程知识, 可以收藏一下本人的多线程学习专栏, 里面会持续更新本人的学习记录, 跟随我一起不断学习.
✨ 感谢你们的耐心阅读, 博主本人也是一名学生, 也还有需要很多学习的东西. 写这篇文章是以本人所学内容为基础, 日后也会不断更新自己的学习记录, 我们一起努力进步, 变得优秀, 小小菜鸟, 也能有大大梦想, 关注我, 一起学习.

再次感谢你们的阅读, 你们的鼓励是我创作的最大动力!!!!!

相关文章:

【多线程进阶】线程安全的集合类

文章目录 前言1. 多线程环境使用 ArrayList2. 多线程环境使用队列3. 多线程环境使用哈希表3.1 HashTable3.2 ConcurrentHashMap 总结 前言 本文主要讲解 Java 线程安全的集合类, 在之前学习过的集合类中, 只有 Vector, Stack, HashTable, 是线程安全的, 因为在他们的关键方法中…...

016 Spring Boot + Vue 图书管理系统

Spring Boot Vue 图书馆管理系统(library-system) 本地快捷预览项目 第一步:运行 db 文件夹下的springboot-vue.sql(询问作者获取),创建springboot-vue数据库 第二步:修改后端数据库配置文件,启动后端 …...

C语言中volatile/register/const/static/extern/auto关键字的作用

目录 一、volatile 二、register详解 三、const详解 四、static详解 五、extern详解 语法 作用 六、auto详解 突然想总结一下这些关键字的作用,灵活使用这些对程序的可靠性和速率都有提高 一、volatile volatile是防止编译器优化,如果是高频繁…...

docker compose的安装和使用

docker-copose 介绍 docker-compose 是一个容器编排工具(自动化部署、管理); 它用来在单台 Linux 服务器上运行多个 Docker 容器; docker-compose 使用YAML文件来配置所有需要运行的 Docker 容器,该 YAML 文件的默认名称为 docker-compose.…...

/lib64/libstdc++.so.6: version `GLIBCXX_3.4.21‘ not found (required by

在某项目中遇到下面的错误, ./model2trt_v2: /lib64/libstdc.so.6: version GLIBCXX_3.4.21 not found (required by ./model2trt_v2) ./model2trt_v2: /lib64/libstdc.so.6: version GLIBCXX_3.4.21 not found (required by ../../../lib/linux_lib/libcuda_utils…...

数字化转型的必备工具:智能呼叫中心系统的应用

数字化转型已经成为企业发展的必然趋势,在这个过程中,智能呼叫中心系统成为了一个不可或缺的工具。智能呼叫中心系统通过整合各种通信渠道和自动化技术,为企业提供了高效、智能的客户服务解决方案。 首先,系统能够集成多种通信渠…...

macOS Sonoma 正式版系统已发布,macos14值得更新吗

北京时间9月27日macOS Sonoma 正式版系统发布,为 Mac 带来一系列丰富新功能:优化小组件、升级视频会议、沉浸式游戏体验等,最新macos14值得更新吗?这里根据我一个月的试用beta版本体验来分享一下。 我使用的是M1芯片的MacBook air…...

数据结构-图-最短路径问题

最短路径问题 单源最短路径Dijkstra算法原理代码实现 Bellman-Ford算法原理代码实现SPFA优化SPFA代码实现 多元最短路径Floyd-Warshall算法原理代码实现 单源最短路径 🚀最短路径:从图G的某个顶点出发到达另一个顶点的最短路径,其中最短是指…...

弹性资源组件elastic-resource设计(二)-集群

简介 弹性资源组件提供动态资源能力,是分布式系统关键基础设施,分布式datax,分布式索引,事件引擎都需要集群和资源的弹性资源能力,提高伸缩性和作业处理能力。 本文介绍弹性资源组件的设计,包括架构设计和详细设计,指导开发人员代码开发,设计基于《flink原理源码分析(一…...

Flink学习笔记(一):Flink重要概念和原理

文章目录 1、Flink 介绍2、Flink 概述3、Flink 组件介绍3.1、Deploy 物理部署层3.2、Runtime 核心层3.3、API&Libraries 层3.4、扩展库 4、Flink 四大基石4.1、Checkpoint4.2、State4.3、Time4.4、Window 5、Flink 的应用场景5.1、Event-driven Applications【事件驱动】5.…...

网络中的一些基本概念

数据共享本质是网络数据传输 ,即计算机之间通过网络来传输数据,也称为 网络通信 。 根据网络互连的规模不同,可以划分为局域网和广域网。 局域网 LAN 局域网,即 Local Area Network ,简称 LAN 。 Local 即标识了局…...

mysql中varchar长度为多少

一. varchar存储规则: 4.0版本以下,varchar(20),指的是20字节,如果存放UTF8汉字时,只能存6个(每个汉字3字节) 5.0版本以上,varchar(20),指的是20字符,无论存…...

python+selenium实现UI自动化(入门篇)

一、基础准备。 python环境安装,参考:CSDN pycharm安装,参考:CSDN 谷歌浏览器驱动配置,参考:CSDN二、新建pycharm项目 截图中,上面是项目地址(可以提前在指定位置创建文件夹&#xf…...

深度学习基础知识 nn.Sequential | nn.ModuleList | nn.ModuleDict

深度学习基础知识 nn.Sequential | nn.ModuleList | nn.ModuleDict 1、nn.Sequential 、 nn.ModuleList 、 nn.ModuleDict 类都继承自 Module 类。2、nn.Sequential、nn.ModuleList 和 nn.ModuleDict语法3、Sequential 、ModuleDict、 ModuleList 的区别…...

【DevOps】搭建你的第一个 Docker 应用栈

搭建你的第一个 Docker 应用栈 1.Docker 集群部署2.第一个 Hello World2.1 获取应用栈各节点所需镜像2.2 应用栈容器节点互联2.3 应用栈容器节点启动2.4 应用栈容器节点的配置2.4.1 Redis Master 主数据库容器节点的配置2.4.2 Redis Slave 从数据库容器节点的配置2.4.3 Redis 数…...

软件测试职业生涯需要编写的全套文档模板,收藏这一篇就够了 ~

作为一名测试工程师,在整个的职业生涯中,会涉及到各种不同类型的文档编写,大体包括如下: 对应文档模板及文档编写视频如下: 一、测试岗位必备的文档 在一个常规的软件测试流程中,会涉及到测试计划、测试方…...

【Kubernetes】Pod——k8s中最重要的对象之一

Pod是什么?如何使用Pod?资源共享和通信Pod 中的存储Pod 联网:跨 Pod 通信 静态 Pod感谢 💖 Pod是什么? Pod是k8s中创建和管理的、最小的可部署的计算单元。它包含一个或多个容器。就像豌豆荚里面包含了多个豌豆一样。…...

vue-cli-service: command not found问题解决

解决方案:重新安装一下: npm install -g vue/cli...

每日一练 | 华为认证真题练习Day117

1、缺省情况下,广播网络上OSPF协议Deadtime是? A. 20s B. 40s C. 10s D. 30s 2、当两台OSPF路由器形成TWO-WAY邻居关系时,LSDB已完成同步,但是SPF算法尚未运行。 A. 对 B. 错 3、以下哪种协议不属于文件传输协? …...

【JVM】垃圾回收(GC)详解

垃圾回收(GC)详解 一. 死亡对象的判断算法1. 引用计数算法2. 可达性分析算法 二. 垃圾回收算法1. 标记-清除算法2. 复制算法3. 标记-整理算法4. 分代算法 三. STW1. 为什么要 STW2. 什么情况下 STW 四. 垃圾收集器1. CMS收集器(老年代收集器&…...

Linux 文件类型,目录与路径,文件与目录管理

文件类型 后面的字符表示文件类型标志 普通文件:-(纯文本文件,二进制文件,数据格式文件) 如文本文件、图片、程序文件等。 目录文件:d(directory) 用来存放其他文件或子目录。 设备…...

SciencePlots——绘制论文中的图片

文章目录 安装一、风格二、1 资源 安装 # 安装最新版 pip install githttps://github.com/garrettj403/SciencePlots.git# 安装稳定版 pip install SciencePlots一、风格 简单好用的深度学习论文绘图专用工具包–Science Plot 二、 1 资源 论文绘图神器来了:一行…...

Java 8 Stream API 入门到实践详解

一、告别 for 循环&#xff01; 传统痛点&#xff1a; Java 8 之前&#xff0c;集合操作离不开冗长的 for 循环和匿名类。例如&#xff0c;过滤列表中的偶数&#xff1a; List<Integer> list Arrays.asList(1, 2, 3, 4, 5); List<Integer> evens new ArrayList…...

安宝特方案丨XRSOP人员作业标准化管理平台:AR智慧点检验收套件

在选煤厂、化工厂、钢铁厂等过程生产型企业&#xff0c;其生产设备的运行效率和非计划停机对工业制造效益有较大影响。 随着企业自动化和智能化建设的推进&#xff0c;需提前预防假检、错检、漏检&#xff0c;推动智慧生产运维系统数据的流动和现场赋能应用。同时&#xff0c;…...

Swift 协议扩展精进之路:解决 CoreData 托管实体子类的类型不匹配问题(下)

概述 在 Swift 开发语言中&#xff0c;各位秃头小码农们可以充分利用语法本身所带来的便利去劈荆斩棘。我们还可以恣意利用泛型、协议关联类型和协议扩展来进一步简化和优化我们复杂的代码需求。 不过&#xff0c;在涉及到多个子类派生于基类进行多态模拟的场景下&#xff0c;…...

连锁超市冷库节能解决方案:如何实现超市降本增效

在连锁超市冷库运营中&#xff0c;高能耗、设备损耗快、人工管理低效等问题长期困扰企业。御控冷库节能解决方案通过智能控制化霜、按需化霜、实时监控、故障诊断、自动预警、远程控制开关六大核心技术&#xff0c;实现年省电费15%-60%&#xff0c;且不改动原有装备、安装快捷、…...

Linux-07 ubuntu 的 chrome 启动不了

文章目录 问题原因解决步骤一、卸载旧版chrome二、重新安装chorme三、启动不了&#xff0c;报错如下四、启动不了&#xff0c;解决如下 总结 问题原因 在应用中可以看到chrome&#xff0c;但是打不开(说明&#xff1a;原来的ubuntu系统出问题了&#xff0c;这个是备用的硬盘&a…...

C# SqlSugar:依赖注入与仓储模式实践

C# SqlSugar&#xff1a;依赖注入与仓储模式实践 在 C# 的应用开发中&#xff0c;数据库操作是必不可少的环节。为了让数据访问层更加简洁、高效且易于维护&#xff0c;许多开发者会选择成熟的 ORM&#xff08;对象关系映射&#xff09;框架&#xff0c;SqlSugar 就是其中备受…...

自然语言处理——Transformer

自然语言处理——Transformer 自注意力机制多头注意力机制Transformer 虽然循环神经网络可以对具有序列特性的数据非常有效&#xff0c;它能挖掘数据中的时序信息以及语义信息&#xff0c;但是它有一个很大的缺陷——很难并行化。 我们可以考虑用CNN来替代RNN&#xff0c;但是…...

实现弹窗随键盘上移居中

实现弹窗随键盘上移的核心思路 在Android中&#xff0c;可以通过监听键盘的显示和隐藏事件&#xff0c;动态调整弹窗的位置。关键点在于获取键盘高度&#xff0c;并计算剩余屏幕空间以重新定位弹窗。 // 在Activity或Fragment中设置键盘监听 val rootView findViewById<V…...