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

文章目录

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

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

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

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

相关文章

【debian 12】:debian系统切换中文界面

目录 目录 项目场景 基础参数 原因分析 解决方案 1.ctrlaltT 打开终端 2.查询当前语言环境(我的已经设置成了中文 zh_CN.UTF-8) 3.打开语言配置界面 4.最后一步:重启 不要放弃任何一个机会! 项目场景: 这两…

【Linux基础】Linux的基本指令使用(超详细解析,小白必看系列)

👉系列专栏:【Linux基础】 🙈个人主页:sunnyll 目录 💦 ls 指令 💦 pwd指令 💦cd指令 💦touch指令 💦mkdir指令(重要) 💦rmdir指令…

产品需求分析师的基本职责

产品需求分析师的基本职责1 职责 1、主要对用友司库云产品进行调研及产品规划; 2、根据司库云业务需求进行详细需求的用户故事、原型设计、需求分析、详细需求文档编写等; 3、进行产品的需求管理、需求验证、产品演示等需求工作; 4、配合开发、UE人员完成对产品的开发任务;…

MOM与MES管理系统有哪些本质上的区别

随着企业业务的不断发展,许多制造企业开始面临车间管理失控、生产不透明等问题。这时候,很多企业选择上线MES生产管理系统来提高生产管理水平。然而,随着企业业务的不断拓展,MES系统也逐渐暴露出其局限性。于是,MOM平台…

高端品牌如何利用软文抓住顾客的心?

如今高端品市场价值巨大,但之前由于“口罩”影响和冲击,高端品牌的线上销售份额占比较少,同时得益于互联网和新媒体技术的发展,高端品的利润来源大多数是线上推广进行销售,而软文就是高端品常用的推广方式,…

(五)激光线扫描-位移台标定

线激光属于主动测量方式,但是由于线激光的特性,我们只能通过提取激光中心线获取这一条线上的高度信息,那么要进行三维重建的话,就需要通过平移或者是旋转的方式,来让线激光扫描被测物体的完整轮廓,也就是整个表面。激光线的密度越高还原出来的物体越细腻,但由于数据量大…

VUE(递归)语法没错,但报 ESLint: ‘formatToTree‘ is not defined.(no-undef)

原因:ESLint(JavaScript 检查器)不允许有未定义的函数,但在递归语法中,自身需要调用自身,则嵌套在里面的函数就会被认为是没定义。 解决办法: 在项目根目录下找到.eslintrc.js文件,文件路径如下图&#xff…

工业路由器项目应用(4g+5g两种工业路由器项目介绍)

引言: 随着工业智能化的不断发展,工业路由器在各个领域的应用越来越广泛。本文将介绍两个工业路由器项目的应用案例,一个是使用SR500 4g工业路由器,另一个是使用SR800 5g工业路由器。 详情:https://www.key-iot.com/i…

Linux CentOS7 yum仓库

在windows下安装一个软件很轻松,只要双击setup或者.exe的文件,安装提示连续“下一步”即可,然而linux系统下安装一个软件似乎并不那么轻松,因为我们不是在图形界面下。 本文我们将讨论如何在linux下安装一个软件。 一、linux软件…

SpringBoot整合POI实现Excel文件读写操作

1.环境准备 1、导入sql脚本: create database if not exists springboot default charset utf8mb4;use springboot;create table if not exists user (id bigint(20) primary key auto_increment comment 主键id,username varchar(255) not null comment 用…

Spring【@Resource、@Autowired+lombook+Bean的生命周期】

Resource 和 Autowired 的区别 在Spring中找Bean的两种方式:①先根据类型查找②再根据名称查找 Autowired先根据类型查找,再根据名称查找【根据上述查找结果不唯一,再添加一个 Qualifier(value“”),就可以查找】 Resource先根据名…

unity中绑定动画的行为系统

主要代码逻辑是创建一个action队列,当动画播放结束时就移除队头,执行后面的事件 public class Enemy : MonoBehaviour {public event Action E_AnimatorFin;//当动画播放完毕时public Action DefaultAction;//默认事件public Dictionary<Action, string> EventAnimator n…