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

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 开始之后,就成了直接在链表头结点,加锁的形式

相关文章:

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

文章目录 1. 多线程环境使用 ArrayList1. 1 Collections.synchronizedList(new ArrayList)1.2 CopyOnWriteArrayList 2. 多线程环境使用队列2.1 ArrayBlockingQueue2.2 LinkedBlockingQueue2.3 PriorityBlockingQueue2.4 TransferQueue 3. 多线程环境使用哈希表3.1 Hashtable3.…...

明明随机数

明明想在学校中请一些同学一起做一项问卷调查&#xff0c;为了实验的客观性&#xff0c;他先用计算机生成了N个1到1000之间的随机整数(N<100)&#xff0c;对于其中重复的数字&#xff0c;只保留一个&#xff0c;把其余相同的数去掉&#xff0c;不同的数对应着不同的学生的学…...

优思学院|如何建立公司运营指标体系?如何推行六西格玛改进运营指标?

关键绩效指标 (KPI) 是测量您团队或组织朝重要商业目标进展表现如何的量化指标&#xff0c;组织会在多个层面使用 KPI&#xff0c;这视乎您想要追踪何指标而定&#xff0c;您可以设定全组织的、特定团队的、或甚至是个人 KPI。 良好的KPI能让公司管理者掌握组织的营运是否进度…...

vue2 echarts不同角色多个类型数据的柱状图

前端代码&#xff1a; 先按照echarts插件。在页面里引用 import * as echarts from "echarts";设置div <div style"width:100%;height:250px;margin-top: 4px;" id"addressChart"></div>方法: addressEcharts() {const option {g…...

Mysql表的数据类型

数据类型 https://www.sjkjc.com/mysql/varchar/ MySQL 中的数据类型包括以下几个大类&#xff1a; 字符串类型 数字类型 日期和时间类型 二进制类型 地理位置数据类型 JSON 数据类型 MySQL 字符串数据类型 VARCHAR&#xff1a;纯文本字符串&#xff0c;字符串长度是可变的…...

c语言单向链表

看如下代码&#xff0c;这是一个完整的可运行的c源文件&#xff0c;要注意的点&#xff1a; c语言程序运行不一定需要头文件NULL其实是 (void*)0&#xff0c;把指针赋值成(void*)0,就是防止程序员不想该指针被引用的时候被引用&#xff0c;引用地址为0的值程序会引起系统中断&…...

『番外篇三』Swift “乱弹”之带索引遍历异步序列(AsyncSequence)

概览 在 Swift 开发中,我们往往在遍历集合元素的同时希望获得元素对应的索引。在本课中,我们将向小伙伴们展示除 enumerated() 方法之外的几种实现思路。在玩转普通集合之后,我们将用“魔法棒”进一步搞定异步序列带索引遍历的实现。 在本篇博主中,您将学到以下内容: 概…...

学习JVM

java虚拟机 流程&#xff1a;helloworld.java----(javac编译)----helloworld.class-------(java运行)——JVM——机器码JVM功能 *解释和运行 *内存管理 *即时编译&#xff08;跨平台-慢一点&#xff09;jit &#xff08;反复用到的代码 解释保存再内存里面&#xff09;…...

Oracle MongoDB

听课的时候第一次碰到&#xff0c;可以了解一下吧&#xff0c;就直接开了墨者学院的靶场 #oracle数据库 Oracle数据库注入全方位利用 - 先知社区 这篇写的真的很好 1.判断注入点 当时找了半天没找到 看样子是找到了&#xff0c;测试一下看看 id1 and 11 时没有报错 2.判断字段…...

Linux-RedHat系统-安装 中间件 Tuxedo

安装步聚 一、中间件安装包&#xff1a; tuxedo121300_64_Linux_01_x86 Tuxedo下载地址&#xff1a; Oracle Tuxedo Downloads 二、新建用户&#xff1a; &#xff08;创建Oracle用户时&#xff0c;需要root权限操作&#xff09; 创建用户&#xff1a; # useradd oracle …...

PHP中的依赖注入是怎样的?

依赖注入&#xff08;Dependency Injection&#xff0c;DI&#xff09;是一种设计模式&#xff0c;它用于解耦组件之间的依赖关系&#xff0c;提高代码的可维护性、可测试性和灵活性。在 PHP 中&#xff0c;依赖注入通常通过构造函数注入、方法注入或属性注入来实现。 以下是依…...

Python求小于m的最大10个素数

为了找到小于m的最大10个素数&#xff0c;我们首先需要确定m的值。然后&#xff0c;我们可以使用一个简单的算法来检查每一个小于m的数字是否是素数。 下面是一个Python代码示例&#xff0c;可以找到小于m的最大10个素数&#xff1a; def is_prime(n): if n < 1: …...

系统的安全性设计

要设计一个安全的系统&#xff0c;除了要了解一些前面讲到的常用的保护手段和技术措施外&#xff0c;还要对系统中可能出现的安全问题或存在的安全隐患有充分的认识&#xff0c;这样才能对系统的安全作有针对性的设计和强化&#xff0c;即“知己知彼&#xff0c;百战百胜”。 下…...

美容店预约小程序搭建指南

随着互联网的发展&#xff0c;越来越多的传统行业开始尝试将业务与互联网相结合&#xff0c;以提供更加便捷、高效的服务。美容行业也不例外。本文将通过使用第三方制作平台&#xff0c;如乔拓云网&#xff0c;指导您如何搭建一个美观实用的美容店预约小程序&#xff0c;帮助您…...

AI:ElasticSearch

ElasticSearch是一款开源的分布式搜索引擎和数据分析引擎&#xff0c;主要用于处理海量数据并提供近实时的搜索和分析功能。它具有全文检索、结构化检索和数据分析等特点&#xff0c;能够满足各种复杂的搜索需求。ElasticSearch使用Java编写&#xff0c;可以运行在多个服务器上…...

如何用 Python 代码打包成一个可执行的 exe 文件?

将Python代码打包成可执行的EXE文件通常需要使用第三方工具&#xff0c;其中PyInstaller是一个流行的选择。PyInstaller可以将Python脚本打包成独立的可执行文件&#xff0c;无需用户安装Python解释器。 打包Python代码成EXE文件的步骤 步骤1&#xff1a;安装PyInstaller 首…...

【Hive】——CLI客户端(bin/beeline,bin/hive)

1 HiveServer、HiveServer2 2 bin/hive 、bin/beeline 区别 3 bin/hive 客户端 hive-site.xml 配置远程 MateStore 地址 XML <?xml version"1.0" encoding"UTF-8" standalone"no"?> <?xml-stylesheet type"text/xsl" hre…...

简约大气视频制作模板PR剪辑素材PR项目工程文件

Premiere Pro模板&#xff0c;简约大气视频剪辑素材PR项目工程文件&#xff08;包含手机竖屏分辨率&#xff09;&#xff0c;包含24个媒体占位符和9个文本占位符。可以编辑和自定义文本占位符和媒体占位符。用来展示照片视频制作。包含视频教程。 来自PR模板网&#xff1a;http…...

Guarded Suspension(担保挂起)设计模式

当线程访问某个对象时&#xff0c;发现条件不满足&#xff0c;暂时挂起等待条件满足时再次访问。Guarded Suspension模式是一个非常基础的模式&#xff0c;主要关注&#xff08;临界值&#xff09;不满足时将操作的线程正确挂起&#xff0c;以防止出现数据不一致或者操作超过临…...

禾匠榜店商城系统 RCE漏洞复现

0x01 产品简介 禾匠榜店商城系统是浙江禾匠信息科技有限公司的一套基于PHP和MySQL的商城系统。 0x02 漏洞概述 禾匠榜店商城系统的api/testOrderSubmit模块下的preview方法存在命令执行漏洞,攻击者可以向服务器写入木马文件,直接获取服务器权限 0x03 漏洞概述 FOFA:bod…...

观成科技:隐蔽隧道工具Ligolo-ng加密流量分析

1.工具介绍 Ligolo-ng是一款由go编写的高效隧道工具&#xff0c;该工具基于TUN接口实现其功能&#xff0c;利用反向TCP/TLS连接建立一条隐蔽的通信信道&#xff0c;支持使用Let’s Encrypt自动生成证书。Ligolo-ng的通信隐蔽性体现在其支持多种连接方式&#xff0c;适应复杂网…...

CVPR 2025 MIMO: 支持视觉指代和像素grounding 的医学视觉语言模型

CVPR 2025 | MIMO&#xff1a;支持视觉指代和像素对齐的医学视觉语言模型 论文信息 标题&#xff1a;MIMO: A medical vision language model with visual referring multimodal input and pixel grounding multimodal output作者&#xff1a;Yanyuan Chen, Dexuan Xu, Yu Hu…...

以下是对华为 HarmonyOS NETX 5属性动画(ArkTS)文档的结构化整理,通过层级标题、表格和代码块提升可读性:

一、属性动画概述NETX 作用&#xff1a;实现组件通用属性的渐变过渡效果&#xff0c;提升用户体验。支持属性&#xff1a;width、height、backgroundColor、opacity、scale、rotate、translate等。注意事项&#xff1a; 布局类属性&#xff08;如宽高&#xff09;变化时&#…...

条件运算符

C中的三目运算符&#xff08;也称条件运算符&#xff0c;英文&#xff1a;ternary operator&#xff09;是一种简洁的条件选择语句&#xff0c;语法如下&#xff1a; 条件表达式 ? 表达式1 : 表达式2• 如果“条件表达式”为true&#xff0c;则整个表达式的结果为“表达式1”…...

CocosCreator 之 JavaScript/TypeScript和Java的相互交互

引擎版本&#xff1a; 3.8.1 语言&#xff1a; JavaScript/TypeScript、C、Java 环境&#xff1a;Window 参考&#xff1a;Java原生反射机制 您好&#xff0c;我是鹤九日&#xff01; 回顾 在上篇文章中&#xff1a;CocosCreator Android项目接入UnityAds 广告SDK。 我们简单讲…...

零基础设计模式——行为型模式 - 责任链模式

第四部分&#xff1a;行为型模式 - 责任链模式 (Chain of Responsibility Pattern) 欢迎来到行为型模式的学习&#xff01;行为型模式关注对象之间的职责分配、算法封装和对象间的交互。我们将学习的第一个行为型模式是责任链模式。 核心思想&#xff1a;使多个对象都有机会处…...

蓝桥杯3498 01串的熵

问题描述 对于一个长度为 23333333的 01 串, 如果其信息熵为 11625907.5798&#xff0c; 且 0 出现次数比 1 少, 那么这个 01 串中 0 出现了多少次? #include<iostream> #include<cmath> using namespace std;int n 23333333;int main() {//枚举 0 出现的次数//因…...

代码随想录刷题day30

1、零钱兑换II 给你一个整数数组 coins 表示不同面额的硬币&#xff0c;另给一个整数 amount 表示总金额。 请你计算并返回可以凑成总金额的硬币组合数。如果任何硬币组合都无法凑出总金额&#xff0c;返回 0 。 假设每一种面额的硬币有无限个。 题目数据保证结果符合 32 位带…...

return this;返回的是谁

一个审批系统的示例来演示责任链模式的实现。假设公司需要处理不同金额的采购申请&#xff0c;不同级别的经理有不同的审批权限&#xff1a; // 抽象处理者&#xff1a;审批者 abstract class Approver {protected Approver successor; // 下一个处理者// 设置下一个处理者pub…...

Linux nano命令的基本使用

参考资料 GNU nanoを使いこなすnano基础 目录 一. 简介二. 文件打开2.1 普通方式打开文件2.2 只读方式打开文件 三. 文件查看3.1 打开文件时&#xff0c;显示行号3.2 翻页查看 四. 文件编辑4.1 Ctrl K 复制 和 Ctrl U 粘贴4.2 Alt/Esc U 撤回 五. 文件保存与退出5.1 Ctrl …...