Java 多线程系列Ⅶ(线程安全集合类)

线程安全集合类

  • 前言
  • 一、多线程使用线性表
  • 二、多线程使用栈和队列
  • 三、多线程下使用哈希表


前言

在数据结构中,我们学习过 Java 的内置集合,但是我们知道,我们学过的大多数集合类都是线程不安全的,少数如 VectorStackHashTable 是线程安全的,但这些都是一些比较“粗糙”的类(在所有方法上加了 synchronized 锁),一般不建议使用。

那么当我们想要在多线程下使用集合类该怎么处理呢?

一、多线程使用线性表

方式1:手动给会出现线程安全问题的逻辑加锁。

例如多个线程修改 ArrayList,此时可能出现问题,就可以给修改操作进行加锁。

方式2:使用 Collections.synchronizedList(); 封装

将想要使用的线性表用上述方法封装起来,相当于给集合里的关键方法加上了锁。

方式3:使用使用 CopyOnWriteArrayList

CopyOnWriteArrayList 原理

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

  2. 这样做的好处是我们可以对 CopyOnWriteArrayList 容器进行并发的读,而不需要加锁(只有在写时加锁),因为当前容器不会添加任何元素。

  3. 所以说 CopyOnWriteArrayList 容器采用的是一种读写分离的思想,读和写不同的容器。

优点:

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

缺点:

  • 在修改时需要重新拷贝容器,占用内存较多。
  • 新写的数据不能被第一时间读取到,即可能出现“脏读”问题。

二、多线程使用栈和队列

多线程使用栈和队列,我们可以直接使用 Java 标准库提供的阻塞队列,因为带有阻塞功能,这些集合在多线程下是线程安全的:

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

三、多线程下使用哈希表

哈希表也是我们经常会使用到的集合类,而标准库提供了 3 种哈希表,3 种哈希表之间的区别也是一个非常重要的知识点,下面就花点时间,对比一下 HashMapHashTableConcurrentHashMap

(1)HashMap

HashMap 不必多说,这就是一个在单线程下使用的哈希表,本身是不安全的。

(2)HashTable

HashTable 是对其中的公共方法加上了 synchronized 锁,其实就想当于给整个哈希表上了锁。如果多个线程访问同一个 HashTable 就和产生锁竞争,而且一旦触发扩容就由该线程完成整个扩容过程,效率会非常低。我们可以简单画个图理解一下:

(3)ConcurrentHashMap

ConcurrentHashMap 在 HashTable 的基础上做了一些优化:

Java1.7 中主要的优化手段是:

使用的是分段锁技术, 简单的说就是把若干个哈希桶分成一个"段" (Segment),针对每个段分别加锁。目的也是为了降低锁竞争的概率。当两个线程访问的数据恰好在同一个段上的时候,才触发锁竞争。

Java1.8 中的优化

优化1:读写操作(最关键的优化)

在Java1.8中取消了分段锁,直接给每个哈希桶/每个链表,分配了一个锁,就是以每个链表的头结点对象作为锁对象。在读操作上取消了加锁,使用了 volatile 保证从内存读取结果。同样我们画个图理解:

举个例子:

假如现在有两个线程,插入两个元素。线程 1 插入元素对应下标为 1 的链表上;线程 2 插入的元素,对应在下标为 2
的链表上。此时就相当于是两个线程修改不同的变量,显然是没有线程安全问题的。ConcurrentHashMap,每次插入操作只是针对对应的链表加锁,操作不同的链表就是针对不同的锁加锁,不会产生锁竞争。因此这就导致大部分加锁实际上是没有所冲突的,而这里的加锁操作开销也就微乎其微了。如果此时使用的是 HashTable,由于是对整个哈希表加锁,这两个插入依然会对同一个 this 产生锁竞争,产生阻塞等待。

优化2:重复利用CAS特性
例如更新、获取元素个数直接使用 CAS 完成,不必加锁。

优化3:优化扩容机制(化整为零)
我们知道哈希表中有一个参数叫做“负载因子”。如果元素过多,导致负载因子过大就要考虑扩容。

扩容就需要重新申请内存空间,把元素从旧的哈希表上删掉,插入到新的哈希表上。但是如果哈希表元素非常多,搬运一次就会导致这一次put操作非常卡顿。

而对于 ConcurrentHashMap 的扩容策略——化整为零。发现需要扩容的线程,只需要创建一个新的数组(更大的内存空间),同时只搬几个元素过去。扩容期间,新老数组同时存在。

后续每个来操作 ConcurrentHashMap 的线程,都会参与搬家的过程。每个操作负责搬运一小部分元素,搬完最后一个元素再把老数组删掉。在此期间,插入只往新数组加,查找需要同时查新数组和老数组。

优化4:底层实现
将原来 数组 + 链表 的实现方式改进成 数组 + 链表 / 红黑树 的方式。当链表较长的时候(大于等于8 个元素)就转换成红黑树。

使用 HashMap、HashTable、ConcurrentHashMap 冷知识:

  • HashMap:key 允许为 null
  • HashTable:key 不允许为 null
  • ConcurrentHashMap:key 不允许为 null

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

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

相关文章

【基础计算机网络1】认识计算机网络体系结构,了解计算机网络的大致模型(下)

前言 在上一篇我们主要介绍了有关计算机网络概述的内容,下面这一篇我们将来介绍有关计算机网络体系结构与参考模型的内容。这一篇博客紧紧联系上一篇博客。 这一篇博客主要内容是:计算机网络体系结构与参考模型,主要是计算机网络分层结构、协…

easypoi和poi版本兼容问题记录

最近在开发导出word的功能,遇到下面的问题 提示xml报错的问题,我一度以为是项目换了java11造成的。经过询问朋友,得知有可能是版本冲突造成的,就猛然想起来,我的项目里面还引入了poi这个包。 于是我吧poi的版本降低到了…

从零开发一款ChatGPT VSCode插件

‍本文作者是360奇舞团开发工程师 引言 OpenAI发布了ChatGPT,就像是给平静许久的互联网湖面上扔了一颗重磅炸弹,刹那间所有人都在追捧学习它。究其原因,它其实是一款真正意义上的人工智能对话机器人。它使用了深度学习技术,通过大…

【源码】JavaWeb+Mysql招聘管理系统 课设

简介 用idea和eclipse都可以&#xff0c;数据库是mysql&#xff0c;这是一个Java和mysql做的web系统&#xff0c;用于期末课设作业 cout<<"如果需要的小伙伴可以http://www.codeying.top";可定做课设 线上招聘平台整合了各种就业指导资源&#xff0c;通过了…

PCL入门(一):ubuntu20使用apt安装pcl

目录 0. 背景1. apt安装的版本2. 更新apt源3. apt安装命令4. 测试 0. 背景 使用源码安装pcl较为麻烦&#xff0c;因为存在依赖库vtk&#xff0c;flann&#xff0c;boost&#xff0c;eigen等&#xff0c;都不太好安装&#xff0c;因此采用apt方式安装。 下面内容主要参考博客《…

Redis之string类型的三大编码解读

目录 string类型的三大编码 int 编码 embstr 编码 raw 编码 明明没有超过阈值,为什么变成raw&#xff1f; 查看数据类型相关命令 redis看看类型:type key 看看编码:object encoding debug结构:debug object person 在 Redis 中&#xff0c;String 类型的数据结构并…

【linux基础(五)】Linux中的开发工具(上)---yum和vim

&#x1f493;博主CSDN主页:杭电码农-NEO&#x1f493;   ⏩专栏分类:Linux从入门到开通⏪   &#x1f69a;代码仓库:NEO的学习日记&#x1f69a;   &#x1f339;关注我&#x1faf5;带你学更多操作系统知识   &#x1f51d;&#x1f51d; Linux中的开发工具 1. 前言2.…

让照片动起来的软件,轻松制作照片动效

随着社交媒体的日益普及&#xff0c;我们对于照片的要求也越来越高。普通的照片已经不能满足我们的需求&#xff0c;我们希望照片更加生动有趣。照片动效便应运而生&#xff0c;它可以让照片动起来&#xff0c;吸引更多的注意力&#xff0c;让照片更加生动有趣。 照片动效制作起…

C盘清理教程

C盘清理教程 首先使用space Sniffer 扫一下c盘&#xff0c;然后看一下到底是哪个文件这么大 第二步&#xff0c;创建软链接。 首先将我们需要移动的文件的当前路径拷贝下来&#xff1a;C:\Users\Tom\Desktop\test-link\abc\ghi.txt 然后假设剪切到D盘下&#xff1a;D:\ghi.…

颜色代码对照表

颜色代码对照表 各颜色代码: 1 白色 #FFFFFF 2 红色 #FF0000 3 绿色 #00FF00 4 蓝色 #0000FF 5 牡丹红 #FF00FF 6 青色 #00FFFF 7 黄色 #FFFF00 8 黑色 #000000 9 海蓝 #70DB93 …

FPGA原理与结构——时钟IP核的使用与测试

一、前言 本文介绍xilinx的时钟IP核 Clocking Wizard v6.0的具体使用与测试过程&#xff0c;在学习一个IP核的使用之前&#xff0c;首先需要对于IP核的具体参数和原理有一个基本的了解&#xff0c;具体可以参考&#xff1a; FPGA原理与结构——时钟IP核原理学习https://blog.c…

用于非线性多载波卫星信道的多输入多输出符号速率信号数字预失真器DPD(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

Docker使用及本地Yolov5打包教程

1. Docker的安装 注意&#xff1a;官方也提供了直接Pull Yolov5的渠道&#xff1a; docker pull ultralytics/yolov5 详见&#xff1a;https://hub.docker.com/r/ultralytics/yolov5 --------------------------------------------------以下正文------------------------…

SOC 2.0安全运营中心

SOC&#xff0c;安全运营中心&#xff0c;为取得其最佳效果&#xff0c;以及真正最小化网络风险&#xff0c;需要全员就位&#xff0c;让安全成为每个人的责任。 早在几年前&#xff0c;企业就开始创建SOC来集中化威胁与漏洞的监视和响应。第一代SOC的目标&#xff0c;是集中管…

黑马JVM总结(五)

&#xff08;1&#xff09;方法区 它是所有java虚拟机 线程共享的区&#xff0c;存储着跟类的结构相关的信息&#xff0c;类的成员变量&#xff0c;方法数据&#xff0c;成员方法&#xff0c;构造器方法&#xff0c;特殊方法&#xff08;类的构造器&#xff09; 方法区在虚拟机…

Linux命令200例:write用于向特定用户或特定终端发送信息

&#x1f3c6;作者简介&#xff0c;黑夜开发者&#xff0c;CSDN领军人物&#xff0c;全栈领域优质创作者✌。CSDN专家博主&#xff0c;阿里云社区专家博主&#xff0c;2023年6月csdn上海赛道top4。 &#x1f3c6;数年电商行业从业经验&#xff0c;历任核心研发工程师&#xff0…

如何提取视频中的音频?几个步骤轻松提取

在现今社交媒体的风靡下&#xff0c;许多人都会使用手机录制视频来记录生活中的美好瞬间。有时候&#xff0c;我们也会想要提取视频中的音频&#xff0c;例如将自己的演讲录音分发给听众。本文将会介绍如何在手机上提取视频中的音频以及需要注意的事项。 使用应用程序 首先&am…

如何使用bat脚本启动指定目录下的jar包

士别三日&#xff0c;当刮目相待。——《三国志》 为了将一个java程序封装成一个简单易用的小工具&#xff0c;使用bat脚本启动jar包。 在txt文档中&#xff0c;键入&#xff1a; echo off java -jar %~dp0core\demo.jar 注意&#xff1a; 1、其中“core”是文件夹的名称&am…

更换Eclipse的JDK版本

点击window->Preferences 选择Installed JREs 点击 Add 按钮&#xff0c; 选择Standard VM, 点击 Next。然后选择自己安装的JDK路径

基于改进人工蜂群算法的 K 均值聚类算法(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…