Java EE 多线程之线程安全的集合类

文章目录

  • 1. 多线程环境使用 ArrayList
    • 1. 1 Collections.synchronizedList(new ArrayList)
    • 1.2 CopyOnWriteArrayList
  • 2. 多线程环境使用队列
    • 2.1 ArrayBlockingQueue
    • 2.2 LinkedBlockingQueue
    • 2.3 PriorityBlockingQueue
    • 2.4 TransferQueue
  • 3. 多线程环境使用哈希表
    • 3.1 Hashtable
    • 3.2 ConcurrentHashMap

原来的集合类,⼤部分都不是线程安全的

但是Vector,Stack,HashTable,是线程安全的(不建议⽤),其他的集合类不是线程安全的

针对这些线程不安全的集合类,要想在多线程环境下使用,就需要考虑好 线程安全问题了(加锁)

同时,标准库,也给我们提供了一些搭配的组件,保证线程安全

1. 多线程环境使用 ArrayList

1. 1 Collections.synchronizedList(new ArrayList)

Collections.synchronizedList(new ArrayList)
这个东西会返回一个新的对象,这个新的对象,就相当于给 ArrayList 套了一层外衣
这个外衣就是在方法上直接使用 synchronized 的

1.2 CopyOnWriteArrayList

CopyOnWriteArrayList 称为写实拷贝

比如,两个线程使用同一个 ArrayList ,可能会读,也可能会修改

如果要是两个线程读,可以直接进行读
如果某个线程需要进行修改,就把 ArrayList 复制出一份副本,修改这个副本
于此同时,另一个线程仍然可以读取书库(从原来的数据上进行读取)
一旦这边修改完毕,就会使用修改好的这份数据,替代掉原来的数据(往往就是一个引用赋值)

上述这个过程进行修改,就不需要加锁了


但是上述操作会存在一些问题

  1. 当前操作的 ArrayList 不能太大(拷贝成本,不能太高)
  2. 更适合于一个线程去修改,而不是多个线程同时修改(多个线程去,一个线程修改)

这种场景适合于 服务器的配置更新

可以通过配置文件,来描述配置的详细内容(本身不会很大)

配置的内容会被读到内存中,再由其他的线程,读取这里的内容
但是修改这个配置内容,往往只有一个线程来修改

如果程序员修改了配置文件,通过某种操作(使用命令)让服务器重新加载配置,就可使使用 写实拷贝 的方式

2. 多线程环境使用队列

2.1 ArrayBlockingQueue

基于数组实现的阻塞队列

2.2 LinkedBlockingQueue

基于链表实现的阻塞队列

2.3 PriorityBlockingQueue

基于堆实现的带优先级的阻塞队列

2.4 TransferQueue

最多只包含⼀个元素的阻塞队列

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

HashMap 本⾝不是线程安全的
在多线程环境下使⽤哈希表可以使⽤:
• Hashtable
• ConcurrentHashMap

3.1 Hashtable

Hashtable 保证线程安全,主要就是给关键方法,加上 synchronized
synchronized 是直接加到方法上的(相当于给 this 加锁)

只要两个线程,在同时操作同一个 Hashtable 就会出现锁冲突


但是实际上,对于哈希表来时,锁不一定非要这么加,有些情况,其实并不涉及到线程安全问题

两个不同的 key 映射到同一个数组下标上就会出现 hash 冲突
这个时候,我们可以使用链表来解决 hash 冲突
在这里插入图片描述
按照上述这样的方式,并且在不考虑触发扩容的前提下
操作不同的链表的时候就是线程安全的

相比之下,如果两个线程,操作的是同一个链表,会容易出现问题

如果两个线程,操作的是不同的链表,就根本不用加锁,只有说操作的是同一个链表才需要加锁

3.2 ConcurrentHashMap

ConcurrentHashMap 的改良方式:

  1. ConcurrentHashMap 相对比上述的HashMap,最核心的改进,就是把一个全局的大锁,改进成了 每个链表独立的一把小锁
    这样做大幅度降低了锁冲突的概率
    一个 hash 表,有很多这样的链表,两个线程恰好同时访问一个链表的情况,本身就比较少
  2. 充分利用到了 CAS 特性,把一些不必要加锁的环节给省略加锁了
    比如,需要使用变量记录 hash 表中的元素个数
    此时,就可以使用原子操作(CAS)修改元素个数
  3. ConcurrentHashMap 还有一个激进的操作,针对读操作没有加锁
    读和读之间,读和写之间,都不会有锁竞争
    那么是否会存在“读一半 修改了一半”的数值呢?
    ConcurrentHashMap 在底层编码过程中,比较谨慎的处理了一些细节
    修改的时候会避免使用 ++ – 这种非原子的操作
    使用 = 进行修改,本身就是原子的
    读的时候,要么读的就是写之前的旧值,要么是读到写之后的心智,不会出现读到一个 一半的值
    (写和写之间还是需要加锁的)
  4. ConcurrentHashMap 针对扩容操作,做出了单独的优化
    本身 Hashtable 或者 HashMap 在扩容的时候,都是需要把所有的元素都拷贝一遍(如果元素很多,拷贝就比较耗时)
    比如,用户访问 1000 次,999 次都很流畅,其中一次就卡了(正好这一次触发扩容,导致出现卡顿)
    ConcurrentHashMap 的优化方式就是“化整为零
    一旦需要扩容,确实需要搬运,不是在一次操作中搬运完成,而是分成多次 来搬运
    每次只搬运一部分数据,这样就可以避免这单次操作过于卡顿

ConcurrentHashMap 基本的使用方法和普通的 HashMap 完全一样

在第一点中,我们是怎么把每个链表单独加锁的呢?
其实就是把每个链表的头结点,作为锁对象
synchronized 可以使用任意对象作为锁对象

在这个时候,我们有的时候会提到分段锁
什么是分段锁呢?
在 java 8 之前, ConcurrentHashMap 就是基于分段锁的方式实现的
等到 java 8 开始之后,就成了直接在链表头结点,加锁的形式

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

QT----第三天,Visio stdio自定义封装控件

目录 第三天1 自定义控件封装 源码:CPP学习代码 第三天 1 自定义控件封装 新建一个QT widgetclass,同时生成ui,h,cpp文件 在smallWidget.ui里添加上你想要的控件并调试大小 回到mainwidget.ui,拖入一个widget(因为我们封装的也…

jemeter,断言:响应断言、Json断言

一、响应断言 接口A请求正常返回值如下: {"status": 10013, "message": "user sign timeout"} 在该接口下创建【响应断言】元件,配置如下: 若断言成功,则查看结果树的接口显示绿色,若…

maui 开发音乐播放APP 优化(2)

界面改为&#xff1a; 音量可以调整 。同时当前状态 显示。以及播放音乐.视频有时可以自动播放有时候要手动。 界面代码 <?xml version"1.0" encoding"utf-8" ?> <ContentPage xmlns"http://schemas.microsoft.com/dotnet/2021/maui&quo…

MySQL的事务以及springboot中如何使用事务

事务的四大特性&#xff1a; 概念&#xff1a; 事务 是一组操作的集合&#xff0c;它是不可分割的工作单元。事务会把所有操作作为一个整体&#xff0c;一起向系统提交或撤销操作请求&#xff0c;即这些操作要么同时成功&#xff0c;要么同时失败。 注意&#xff1a; 默认MySQ…

最新UI酒桌喝酒游戏小程序源码,直接上传源码到开发者端即可,带流量主

源码介绍&#xff1a; 2023最新UI酒桌喝酒游戏小程序源码 娱乐小程序源码 带流量主.修改增加了广告位&#xff0c;直接上传源码到开发者端即可。 通过后改广告代码&#xff0c;然后关闭广告展示提交&#xff0c;通过后打开即可。无广告引流。 流量主版本的&#xff08;配合流…

proteus元件合集(一)

LCD LM018L​​ 绿色的LCD寻找方法&#xff1a; 直流电压源 直流电压源寻找方法&#xff1a; 滑动变阻器 滑动变阻器寻找方法&#xff1a; 注意&#xff1a;它出来之后会自动出现那两个红色的。那是电源。

崩坏:星穹铁道【V1.5攻略】五星(金)-遗器主、副词条成长数值参考

星穹铁道中五星遗器词条成长数值攻略&#xff1a; 温馨提示&#xff1a;以下数据会可能会出现一点一点误差&#xff0c;见谅... --------------------------- 一、如图&#xff1a; ----->>细节补充<<----- ①实际数值可能与游戏中不一&#xff0c;若数据出现无法忽…

详解Java中的异常体系结构(throw,throws,try-catch,finally,自定义异常)

目录 一.异常的概念 二.异常的体系结构 三.异常的处理 异常处理思路 LBYL&#xff1a;Look Before You Leap EAFP: Its Easier to Ask Forgiveness than Permission 异常抛出throw 异常的捕获 提醒声明throws try-catch捕获处理 finally的作用 四.自定义异常类 一.异…

深入理解亚信安慧AntDB-T数据库子计划的执行流程

概要&#xff1a; SQL语句在执行时会转换为执行计划&#xff0c;若其中包含了子查询或子链接并且不能被优化&#xff0c;则执行计划会生成子计划&#xff08;查看AntDB的执行计划时看到标记为SubPlan[1] 的部分即为子计划&#xff09;。在整个AntDB数据库中&#xff0c;子计划…

现代C++ 实现单例模式

传统写法有什么问题 如果你了解过单例模式&#xff0c;双重检查锁定模式&#xff08;Double-Checked Locking Pattern&#xff0c;后文简称DCLP&#xff09;的写法你一定不会陌生&#xff0c;甚至你或许认为它是最正确的代码。 class Singleton { public://获取单例Singleton…

MySQL 8.x temp空间不足问题

目录 一、系统环境 二、问题报错 三、问题回顾 四、解决问题 一、系统环境 系统Ubuntu20.04 数据库版本MySQL 8.0.21 二、问题报错 在MySQL上执行一个大的SQL查询报错Error writing file /tmp/MYfd142 (OS errno 28 - No space left on device) Exception in thread …

用C语言实现链队列的基本操作

不多解释&#xff0c;直接上代码&#xff0c;代码已经写了注释&#xff01; //队列链式结构的基本操作&#xff1a; #define _CRT_SECURE_NO_WARNINGS 1 #include<stdio.h> #include<stdlib.h> typedef int QueueElememtType; typedef struct QNode//链队的定义 {…

什么是蜘蛛池,蜘蛛池是什么蚂蚁SEO

蜘蛛池是一种通过大量模拟真实用户行为来提升网站搜索引擎排名的技术。这种技术利用大量的网络爬虫程序&#xff0c;模拟搜索引擎蜘蛛的爬行行为&#xff0c;通过大量的模拟爬行和页面抓取&#xff0c;提高网站的权重和排名。 如何联系蚂蚁seo&#xff1f; baidu搜索&#xf…

如何查看自己的文章是否被数据库收入?【查收查引】

致谢&#xff1a;特别感谢图书馆的蔡老师&#xff0c;告诉我怎么操作&#xff01; 另外&#xff0c;查收查引报告中的文章可以分开开&#xff0c;放在一起开不是必须的。&#xff08;放在一起开大概是院士工作量需要的。不是很了解。&#xff09; 如何查看自己的文章是否被数据…

杰发科技AC7840——CAN通信简介(1)

简介 7840支持4路CAN-FD Demo调试 官网下载demo&#xff0c;烧录&#xff0c;打开串口发现打印如下。原因是没有连接CAN盒子&#xff0c;总线错误。 CAN收发器端波形 CAN_L有信号&#xff0c;CAN_H没有 波形放大 GPIO端波形 有持续波形输出 波形放大查看&#xff0c;有50U…

.NET 反射优化的经验分享

比如针对 GetCustomAttributes 通过反射获取属性的优化,以下例子 // dotnet run -c Release -f net7.0 --filter "*" --runtimes net7.0 net8.0public class Tests{public object[] GetCustomAttributes() => typeof(C).GetCustomAttributes(typeof(MyAttribute…

如何快速将图片转为excel?

一、打开金鸣表格文字识别软件。 二、点击添加文件按钮&#xff0c;在打开的窗口中选择目标图片&#xff0c;然后点击“打开”&#xff0c;将图片添加进待识别的列表中。 三、点击提交识别或识别全部。 四、识别完成后点击“打开文件”即可打开识别好的结果文件&#xff08;EXC…

Enabling Application Engine Tracing 启用应用程序引擎跟踪

Enabling Application Engine Tracing 启用应用程序引擎跟踪 By default, all Application Engine traces are turned off. To see a trace or a combination of traces, set trace options before you run a program. 默认情况下&#xff0c;所有应用程序引擎跟踪都处于关闭…

Python学习笔记(四):函数的定义、函数的返回值、None类型、函数说明文档、函数的嵌套调用、局部变量、全局变量、global关键字

目录 一、函数介绍 1. 函数是&#xff1a; 2. 使用函数的好处是&#xff1a; 二、函数的定义&#xff1a; 三、函数的参数 1.传入参数的功能是&#xff1a; 2.函数的传入参数 - 传参定义 3.注意事项&#xff1a; 4.练习&#xff1a;测量体温 四、函数的返回值 1.函数…

宇视科技视频监控 main-cgi 文件信息泄露漏洞

宇视科技视频监控 main-cgi 文件信息泄露漏洞 一、产品简介二、漏概述三、复现环境四、漏洞检测手工抓包自动化检测 免责声明&#xff1a;请勿利用文章内的相关技术从事非法测试&#xff0c;由于传播、利用此文所提供的信息或者工具而造成的任何直接或者间接的后果及损失&#…