JavaEE:多线程进阶(线程安全的集合类)

文章目录

  • 线程安全的集合类
    • 多线程环境使用ArrayList
    • 多线程环境使用队列
    • 多线程环境使用哈希表
      • Hashtable
      • ConcurrentHashMap


线程安全的集合类

之前学习的集合类大部分都不是线程安全的.
比如ArrayList,Queue,HashMap等等,这都是线程不安全的.

Vector,Stack,Hashtable,这些集合类虽然是线程安全的(内置了synchronized),但是实际上这几个东西并不推荐使用,因为它们都是无脑加锁的.

多线程环境使用ArrayList

  1. 自己加锁

  2. 使用标准库中提供的带锁的List,Collections.synchronizedList(new ArrayList);
    synchronizedList就相当于构造出了一个核心方法,自带synchronized的List.
    在这里插入图片描述

  3. 使用CopyOnWriteArrayList
    这个集合类,没有加锁,但是通过"写实拷贝"来实现的线程安全.通过写时拷贝,避免两个线程同时修改一个变量.
    在这里插入图片描述

    写实拷贝介绍:当我们往一个容器添加元素的时候,不直接往当前容器内添加,而是先将当前容器Copy,复制出一个新的容器,然后在新的容器里添加元素.添加完元素之后,再将原容器的引用指向新的容器.

    在这里插入图片描述

    • 在拷贝过程中,读操作,都仍然读取旧版本的内容.写操作,则是在新版本的内容上修改.
    • 这个修改引用指向的操作,本身是原子的,即使在这个过程中,存在大量的读操作,读取内容.此时,仍然能够确保读到的数据是有效的(读到的数据要么是旧版本的数据,要么是新版本数据,不会是一个"修改了一半"的数据)

    写实拷贝的缺点:

    1. 无法应对多个线程同时修改的情况
    2. 如果涉及到的数据量很大,拷贝起来就非常慢.(占用内存较多)
    3. 新写入的数据不能被第一时间读取到.

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

多线程环境使用队列

  1. ArrayBlockingQueue: 基于数组实现的阻塞队列
    在这里插入图片描述

  2. LinkedBlockingQueue: 基于链表实现的阻塞队列
    在这里插入图片描述

  3. PriorityBlockingQueue: 基于堆实现的带优先级的阻塞队列
    在这里插入图片描述

  4. TransferQueue: 最多只包含一个元素的阻塞队列
    在这里插入图片描述

多线程环境使用哈希表

Hashtable

Hashtable只是简单的把关键方法加上了synchronized关键字.
在这里插入图片描述
在这里插入图片描述
这相当于直接针对Hashtable对象本身加锁.

这样做有几个缺点:

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

ConcurrentHashMap

Hashtable虽然是可选项,但是我们更推荐使用ConcurrentHashMap.
ConcurrentHashMap相比于HashMap和Hashtable来说,它的改进力度非常大.

这个部分的内容非常重要,可以认为是整个Java方向,高频面试题,能排到top5的问题.

  1. ConcurrentHashMap优化了锁的粒度[最核心]
    Hashtable的加锁,就是直接给put/get等方法加上synchronized,也就是给this加锁.
    给this加锁,这就意味着整个哈希表对象,就是一把锁.任何一个针对这个哈希表的操作,都会触发锁竞争.
    ConcurrentHashMap是给每个hash表中的"链表"进行加锁(多把锁).“锁桶”
    在这里插入图片描述
    上述的设定方式,既可以保证线程安全,又可以大大降低锁冲突的概率.只有同时进行两次的两次修改,恰好在修改同一个链表上的元素的时候,才会触发锁竞争.

  2. ConcurrentHashMap引入了CAS原子操作
    针对像size这样的操作,直接借助CAS完成,并不会加锁.

  3. ConcurrentHashMap针对读操作,做了特殊处理.
    上述的加锁,只是针对写操作加锁.
    对于读操作,它是通过volatile以及一些精巧的代码来实现的.确保读操作,不会读到"修改一半的数据".

  4. ConcurrentHashMap针对hash表的扩容,进行了特殊的优化.
    普通hash表扩容,需要创建新的hash表,把元素都搬过去.这一系列操作,很有肯能就在一次put中完成了,这样就会使这次put的开销特别大,耗时非常长.
    ConcurrentHashMap针对hash扩容操作,使用了"化整为零"的思想.
    它不会在一次操作中,把所有的数据搬走,而是一次只搬运一部分.此时后续的每次操作,都会触发一部分key的搬运,最终把所有的key都搬运完成.等到全部元素都搬运完成后,再把老数组删掉.
    在这里插入图片描述
    当新旧数据同时存在的时候

    1. 插入操作,直接插入到新的空间中.
    2. 查询/修改/删除操作,都是需要同时查询旧的空间和新的空间的.

这里的扩容机制,跟B+树很像,B+树有一个优点,查询的开销非常稳定.

小小的补充,在往上查一些关于ConcurrentHashMap的资料的时候,可能会见到"分段锁"这样的说法.它属于ConcurrentHashMap早期的实现方式,它与现在的锁桶,思想上是一样的,但是实现上有差别.
"分段锁"把所有的桶,分段,每一段有一个锁(一个锁,管好几个链表)

它存在几个明显的问题:

  1. 它这里降低锁冲突,做的还不够彻底.
  2. 分段锁的实现方式,更复杂

咱们很多时候学习一些"原理"类的知识,一方面是能够有更好的理解,能够更深度的使用和排查问题.
另一方面,也是学习大佬们的设计理念,等到我们后续遇到了类似的场景,这些理念都可以给我们解决问题提供一些参考.

本文到这里就结束啦~

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

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

相关文章

asynMotorController控制器类

电机控制器的基类,实际的电机控制器从这个类派生 asynMotorController.h头文件 /* asynMotorController.h* 这个文件为asynMotorController定义了基类。* 真实电机控制器从这个类派生。它派生字PortDriver.*/ #ifndef asynMotorController_H #define asynMotorCont…

【初识Linux】Linux下基本指令

01. ls 指令 语法: ls [选项][目录或文件] 功能:对于目录,该命令列出该目录下的所有子目录与文件。对于文件,将列出文件名以及其他信息。 常用选项: -a 列出目录下的所有文件,包括以 . 开头的隐含文件。 -…

Linux实用操作

简介:个人学习分享,如有错误,欢迎批评指正。 一、常用快捷键 ctrl c 强制停止 Linux某些程序的运行,如果想要强制停止它,可以使用快捷键ctrl c 命令输入错误,也可以通过快捷键ctrl c,退出当…

基于vue框架的车辆信息检索系统的设计与实现6eph8(程序+源码+数据库+调试部署+开发环境)系统界面在最后面。

系统程序文件列表 项目功能:车辆信息,事故登记,维修记录,用户,汽车类型,保养记录,违章信息,年检记录 开题报告内容 基于Vue框架的车辆信息检索系统的设计与实现开题报告 一、项目背景与意义 随着汽车市场的不断扩大和车辆保有量的急剧增加,车辆信息的…

【无人机设计与控制】 四轴飞行器的位移控制

摘要 本文介绍了一种四轴飞行器的位移控制方法,并通过Simulink模型进行仿真和验证。该方法通过PID控制器对飞行器的位移进行精确调节,以实现飞行器在三维空间中的稳定定位和路径跟踪。通过参数调节,能够适应不同的飞行任务需求,确…

梨花声音研修院退费配音市场现状分析

配音市场近年来显示出强劲的增长势头,涵盖了影视作品、广告、游戏、动画、电子书、企业宣传片等多个领域。随着全球化进程的加速和数字媒体的快速发展,配音需求不断增加,市场前景广阔。本文将详细探讨配音市场的现状,从市场规模、…

java中实现缓存的几种方式

一、通过HashMap实现缓存 这种方式可以简单实现本地缓存&#xff0c;但是实际开发中不推荐使用&#xff0c;下面我们来实现一下这种方式。 首先创建一个管理缓存的类 public class LocalCache {public static ConcurrentMap<String,String> cache new ConcurrentHashM…

SQL插入、更新和删除数据

SQL插入、更新和删除数据 一、直接向表插入数据 1.1、插入完整的行 这里所说的完整行指的是包含表内所有字段的数据行&#xff1b;假设表中有n个字段&#xff0c;则插入完整行的语法&#xff1a; INSERT INTO 表名或视图名 VALUES(字段1的值,字段2的值,字段3的值,...,字段n的…

基于Java+SpringBoot+Vue+MySQL的地方美食分享网站

作者&#xff1a;计算机学姐 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、JSP、ElementUI等&#xff0c;“文末源码”。 专栏推荐&#xff1a;前后端分离项目源码、SpringBoot项目源码、SSM项目源码 系统展示 基于SpringBootVue的地方美食分享网站【附源码文档】、前后…

【Redis入门到精通一】什么是Redis?

目录 Redis 1. Redis的背景知识 2.Redis特性 3.Redis的使用场景 4.Ubuntu上安装配置Redis Redis Redis在当今编程技术中的地位可以说非常重要&#xff0c;大多数互联网公司内部都在使用这个技术&#xff0c;熟练使用Redis已经成为开发人员的一个必备技能。 本章将带领读者…

JavaScript使用高德API显示地图

前言 在JavaScript中&#xff0c;使用Leaflet库显示地图是一种常见的做法。Leaflet是一个开源的JavaScript库&#xff0c;用于在Web应用程序中创建互动地图。它非常轻量级&#xff0c;易于使用&#xff0c;并且提供了多种功能&#xff0c;使开发者能够轻松地将地图集成到他们的…

“知识启航·新年新题”——2025年粉丝专属学术助力计划

一、活动背景与目的 为了感谢广大粉丝一直以来的支持与厚爱&#xff0c;我们特别推出“知识启航新年新题”2025年粉丝专属学术助力计划。本次活动旨在通过提供免费的开题报告、免费的任务书以及一系列学术指导服务&#xff0c;助力粉丝在新的一年里开启学术与项目研究的新篇章…

C# 获取系统使用情况

一个简单的小工具&#xff0c;主要用来获取当期的电脑信息以及内存的使用情况。本来也没想着写这个玩意&#xff0c;还不如随便下个相关的软件好使&#xff0c;但是前一段时间为了追查系统卡顿的问题&#xff0c;所以就加上了一段统计内存的代码&#xff0c;用来看看是否由这个…

DDComponentForAndroid:探索Android组件化方案

在现代Android应用开发中&#xff0c;随着应用规模的不断扩大&#xff0c;传统的单体应用架构已经无法满足快速迭代和维护的需求。组件化架构作为一种解决方案&#xff0c;可以将应用拆分成多个独立的模块&#xff0c;每个模块负责特定的功能&#xff0c;从而提高代码的可维护性…

PWR电源控制(低功耗模式)

1 PWR简介 1 程序后面是空循环&#xff0c;即使不用也会耗电&#xff0c;所以有了低功耗&#xff08;例如遥控器&#xff09; 2 也要保留唤醒模式&#xff0c;如串口接收数据中断唤醒&#xff0c;外部中断唤醒&#xff0c;RTC闹钟唤醒&#xff0c;在需要工作是&#xff0c;ST…

【redis】redis的特性和主要应用场景

文章目录 redis 的特性在内存中存储数据可编程的扩展能力持久化集群高可用快 redis 的应用场景实时数据存储缓存消息队列 redis 的特性 redis 的一些特性&#xff08;优点&#xff09;成就了它 在内存中存储数据 In-memory data structures MySQL 主要是通过“表”的方式来…

分享基于PDF.JS的移动端PDF阅读器代码

一、前言 在之前的文章《分享基于PDF.js的pdf阅读器代码》里提到了PC端基于PDF.js的阅读器&#xff0c;本文将提供针对移动端的版本。 二、pdfViewer 为了能够直接使用&#xff0c;这里分享一下经过简单修改后能直接使用的pdfViewer代码&#xff1a; pdfViewer代码目录&…

如何在红米手机中恢复已删除的照片?(6 种方式可供选择)

凭借出色的相机和实惠的价格&#xff0c;小米红米系列已成为全球知名品牌。但是&#xff0c;最近有些人抱怨他们在 红米设备上丢失了许多珍贵的图片或视频&#xff0c;并希望弄清楚如何从小米手机恢复已删除的照片。好吧&#xff0c;在小米设备上恢复已删除的视频/照片并不难。…

基于Pytorch框架的深度学习U2Net网络精细天空分割系统源码

第一步&#xff1a;准备数据 头发分割数据&#xff0c;总共有10276张图片&#xff0c;里面的像素值为0和1&#xff0c;所以看起来全部是黑的&#xff0c;不影响使用 第二步&#xff1a;搭建模型 级联模式 通常多个类似U-Net按顺序堆叠&#xff0c;以建立级联模型&#xff0c…

移动端视频编辑SDK解决方案,AI语音识别添加字幕

对于众多Vlog创作者而言&#xff0c;繁琐的字幕添加过程往往成为提升内容质量的绊脚石。为了彻底改变这一现状&#xff0c;美摄科技凭借其深厚的AI技术积累与创新的移动端视频编辑SDK解决方案&#xff0c;推出了革命性的AI语音识别添加字幕功能&#xff0c;让视频创作更加高效、…