【Java EE】线程安全的集合类

目录

  • 🌴多线程环境使用 ArrayList
  • 🎍多线程环境使⽤队列
  • 🍀多线程环境使⽤哈希表
    • 🌸 Hashtable
    • 🌸ConcurrentHashMap
  • ⭕相关面试题
  • 🔥其他常⻅问题

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

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

那如何在多线程环境下安全的使用 集合类呢?

🌴多线程环境使用 ArrayList

1. ⾃⼰使⽤同步机制 (synchronized 或者 ReentrantLock)
前⾯做过很多相关的讨论了. 此处不再展开.可以查看博主之前的博客
2. Collections.synchronizedList(new ArrayList);

synchronizedList 是标准库提供的⼀个基于 synchronized 进⾏线程同步的 List. synchronizedList
的关键操作上都带有 synchronized

3. 使⽤ CopyOnWriteArrayList

CopyOnWrite容器即写时复制的容器。
• 当我们往⼀个容器添加元素的时候,不直接往当前容器添加,⽽是先将当前容器进⾏Copy,复制
出⼀个新的容器,然后新的容器⾥添加元素,
• 添加完元素之后,再将原容器的引⽤指向新的容器。

这样做的好处是我们可以对CopyOnWrite容器进⾏并发的读,⽽不需要加锁,因为当前容器不会添
加任何元素

所以CopyOnWrite容器也是⼀种读写分离的思想,读和写不同的容器。
优点:
在读多写少的场景下, 性能很⾼, 不需要加锁竞争.
缺点:

  1. 占⽤内存较多.
  2. 新写的数据不能被第⼀时间读取到

🎍多线程环境使⽤队列

  1. ArrayBlockingQueue

基于数组实现的阻塞队列

  1. LinkedBlockingQueue

基于链表实现的阻塞队列

  1. PriorityBlockingQueue

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

  1. TransferQueue

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

🍀多线程环境使⽤哈希表

HashMap 本⾝不是线程安全的.

在多线程环境下使⽤哈希表可以使⽤:
Hashtable
ConcurrentHashMap

🌸 Hashtable

只是简单的把关键⽅法加上了 synchronized 关键字
在这里插入图片描述

相当于直接针对 Hashtable 对象本⾝加锁.
• 如果多线程访问同⼀个 Hashtable 就会直接造成锁冲突.
• size 属性也是通过 synchronized 来控制同步, 也是⽐较慢的.
• ⼀旦触发扩容, 就由该线程完成整个扩容过程. 这个过程会涉及到⼤量的元素拷⻉, 效率会⾮常低.

在这里插入图片描述

🌸ConcurrentHashMap

相⽐于 Hashtable 做出了⼀系列的改进和优化. 以 Java1.8 为例

  1. 读操作没有加锁(但是使⽤了 volatile 保证从内存读取结果), 只对写操作进⾏加锁. 加锁的⽅式仍然是⽤ synchronized, 但是不是锁整个对象, ⽽是 "锁桶" (⽤每个链表的头结点作为锁对象), ⼤⼤降低了锁冲突的概率.
  2. 充分利⽤ CAS 特性. ⽐如 size 属性通过 CAS 来更新. 避免出现重量级锁的情况.
  3. 优化了扩容⽅式: 化整为零
  • 发现需要扩容的线程, 只需要创建⼀个新的数组, 同时只搬⼏个元素过去.
  • 扩容期间, 新⽼数组同时存在.
  • 后续每个来操作 ConcurrentHashMap 的线程, 都会参与搬家的过程. 每个操作负责搬运⼀⼩部
    分元素.
  • 搬完最后⼀个元素再把⽼数组删掉.
  • 这个期间, 插⼊只往新数组加.
  • 这个期间, 查找需要同时查新数组和⽼数组
    在这里插入图片描述
    ConcurrentHashMap每个哈希桶都有一把锁,只有两个线程访问的恰好是同一个哈希桶上的数据才会出现锁冲突。

⭕相关面试题

  1. ConcurrentHashMap的读是否要加锁,为什么?

读操作没有加锁. ⽬的是为了进⼀步降低锁冲突的概率. 为了保证读到刚修改的数据, 搭配了 volatile
关键字.

  1. 介绍下 ConcurrentHashMap的锁分段技术?

这个是 Java1.7 中采取的技术. Java1.8 中已经不再使⽤了. 简单的说就是把若⼲个哈希桶分成⼀个
“段” (Segment), 针对每个段分别加锁.
⽬的也是为了降低锁竞争的概率. 当两个线程访问的数据恰好在同⼀个段上的时候, 才触发锁竞争.

  1. ConcurrentHashMap在jdk1.8做了哪些优化?

取消了分段锁, 直接给每个哈希桶(每个链表)分配了⼀个锁(就是以每个链表的头结点对象作为锁对
象).
将原来 数组 + 链表 的实现⽅式改进成 数组 + 链表 / 红⿊树 的⽅式. 当链表较⻓的时候(⼤于等于 8 个
元素)就转换成红⿊树.

  1. Hashtable和HashMap、ConcurrentHashMap 之间的区别?

HashMap: 线程不安全. key 允许为 null
Hashtable: 线程安全. 使⽤ synchronized 锁 Hashtable 对象, 效率较低. key 不允许为 null.
ConcurrentHashMap: 线程安全. 使⽤ synchronized 锁每个链表头结点, 锁冲突概率低, 充分利⽤
CAS 机制. 优化了扩容⽅式. key 不允许为 null

🔥其他常⻅问题

  1. 谈谈 volatile关键字的⽤法?

volatile 能够保证内存可⻅性. 强制从主内存中读取数据. 此时如果有其他线程修改被 volatile 修饰的
变量, 可以第⼀时间读取到最新的值

  1. Java多线程是如何实现数据共享的?

JVM 把内存分成了这⼏个区域:
⽅法区, 堆区, 栈区, 程序计数器.
其中堆区这个内存区域是多个线程之间共享的.
只要把某个数据放到堆内存中, 就可以让多个线程都能访问到.

  1. Java创建线程池的接⼝是什么?参数 LinkedBlockingQueue 的作⽤是什么?

创建线程池主要有两种⽅式:
• 通过 Executors ⼯⼚类创建. 创建⽅式⽐较简单, 但是定制能⼒有限.
• 通过 ThreadPoolExecutor 创建. 创建⽅式⽐较复杂, 但是定制能⼒强.
LinkedBlockingQueue 表⽰线程池的任务队列. ⽤⼾通过 submit / execute 向这个任务队列中
添加任务, 再由线程池中的⼯作线程来执⾏任务.

  1. Java线程共有⼏种状态?状态之间怎么切换的?

• NEW: 安排了⼯作, 还未开始⾏动. 新创建的线程, 还没有调⽤ start ⽅法时处在这个状态.
• RUNNABLE: 可⼯作的. ⼜可以分成正在⼯作中和即将开始⼯作. 调⽤ start ⽅法之后, 并正在 CPU 上
运⾏/在即将准备运⾏ 的状态.
• BLOCKED: 使⽤ synchronized 的时候, 如果锁被其他线程占⽤, 就会阻塞等待, 从⽽进⼊该状态.
• WAITING: 调⽤ wait ⽅法会进⼊该状态.
• TIMED_WAITING: 调⽤ sleep ⽅法或者 wait(超时时间) 会进⼊该状态.
• TERMINATED: ⼯作完成了. 当线程 run ⽅法执⾏完毕后, 会处于这个状态

  1. 在多线程下,如果对⼀个数进⾏叠加,该怎么做?

• 使⽤ synchronized / ReentrantLock 加锁
• 使⽤ AtomInteger 原⼦操作.

  1. Servlet是否是线程安全的?

Servlet 本⾝是⼯作在多线程环境下.
如果在 Servlet 中创建了某个成员变量, 此时如果有多个请求到达服务器, 服务器就会多线程进⾏操
作, 是可能出现线程不安全的情况的

  1. Thread和Runnable的区别和联系?

Thread 类描述了⼀个线程.
Runnable 描述了⼀个任务.
在创建线程的时候需要指定线程完成的任务, 可以直接重写 Thread 的 run ⽅法, 也可以使⽤
Runnable 来描述这个任务.

  1. 多次start⼀个线程会怎么样

第⼀次调⽤ start 可以成功调⽤.
后续再调⽤ start 会抛出 java.lang.IllegalThreadStateException 异常

  1. 有synchronized两个⽅法,两个线程分别同时⽤这个⽅法,请问会发⽣什么?

synchronized 加在⾮静态⽅法上, 相当于针对当前对象加锁.
如果这两个⽅法属于同⼀个实例:
线程1 能够获取到锁, 并执⾏⽅法. 线程2 会阻塞等待, 直到线程1 执⾏完毕, 释放锁, 线程2 获取到锁之
后才能执⾏⽅法内容.
如果这两个⽅法属于不同实例:
两者能并发执⾏, 互不⼲扰.

  1. 进程和线程的区别?

• 进程是包含线程的. 每个进程⾄少有⼀个线程存在,即主线程。
• 进程和进程之间不共享内存空间. 同⼀个进程的线程之间共享同⼀个内存空间.
• 进程是系统分配资源的最⼩单位,线程是系统调度的最⼩单位。

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

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

相关文章

智慧城市的定义是什么?

智慧城市:就是运用信息和通信技术手段感测、分析、整合城市运行核心系统的各项关键信息,从而对包括民生、环保、公共安全、城市服务、工商业活动在内的各种需求做出智能响应。其实质是利用**的信息技术,实现城市智慧式管理和运行,…

【小白必看】永久提升代码/算法能力的6个编程习惯(推荐阅读)

前言 编程和算法能力是当代工程师的核心竞争力之一。想要快速提升自己的编程和算法能力,却苦于没有合适的方法?别担心,今天我将与你分享6个高效编程习惯,让你轻松提升编程和算法能力! 大家好,我是Erik&am…

使用脚本批量下载nuscens数据集

Nuscenes 完整版数据集批量下载 需求: 高速下载Nuscenes完整版数据集。采用google浏览器自带工具下载,速度慢,且容易断。 数据地址 官方地址:https://www.nuscenes.org/nuscenes 如何获取 Nuscenes 数据集的路径 安装插件 ch…

力控软件与多台不同品牌的PLC之间如何实现无线通讯?

在现代化工厂中,除厂级PLC系统外,还存在很多独立的子系统。比如,各个生产车间的PLC系统、或同一生产车间的不同生产流程的PLC系统。对一个大型工厂,由于生产线的不断改造、新老流程的不断更新,这些PLC系统往往是由不同…

【C++庖丁解牛】STL之vector容器的介绍及使用 | vector迭代器的使用 | vector空间增长问题

📙 作者简介 :RO-BERRY 📗 学习方向:致力于C、C、数据结构、TCP/IP、数据库等等一系列知识 📒 日后方向 : 偏向于CPP开发以及大数据方向,欢迎各位关注,谢谢各位的支持 目录 1.1 vector的介绍2 v…

navicat过期了,直接用idea连接mysql

1、我的是社区版,需要下载一个插件,直接搜索安装即可。 2、找到data source,点击mysql 3、你们熟悉的,输入账户密码,点击test Connection测试是否连接成功 4、这个本来是在右边,但是你可以把他挪到左边。 5…

三次握手,四次挥手基本概念及其抓包演示

目录 1.tcp三次握手 2.tcp四次挥手 3.思考问题(面试常考) 3.1 三次握手时可能出现什么攻击? 3.2 为什么是三次握手,可不可以是两次,为什么? ​编辑3.3 四次挥手的过程可以用三次完成吗? 4.抓包演示三次握手四次挥手 1.tcp三次握手 tcp协议特点:面向连接的,可靠的,流式…

【Python】一文详细介绍 plt.rcParamsDefault 在 Matplotlib 中的原理、作用、注意事项

【Python】一文详细介绍 plt.rcParamsDefault 在 Matplotlib 中的原理、作用、注意事项 🌈 个人主页:高斯小哥 🔥 高质量专栏:Matplotlib之旅:零基础精通数据可视化、Python基础【高质量合集】、PyTorch零基础入门教程…

C++的类与对象(三):构造函数、析构函数、对象的销毁顺序

目录 类的6个默认成员函数 构造函数 语法 特性 析构函数 特性 对象的销毁顺序​​​​​​​​​​​​​​ 类的6个默认成员函数 问题:一个什么成员都没的类叫做空类,空类中真的什么都没有吗? 基本概念:任何类在什么都不…

软考73-上午题-【面向对象技术2-UML】-UML中的图4

一、构件图(组件图) 1-1、构件图的定义 展现了,一组构件之间的组织和依赖。 构件图专注于系统的静态实现图。 构件图与类图相关,通常把构件映射为一个、多个类、接口、协作。 【回顾】: 类图展示了一组对象、接口、…

SpringCloud-SpringBoot读取Nacos上的配置文件

在 Spring Boot 应用程序中,可以使用 Spring Cloud Nacos 来实现从 Nacos 服务注册中心和配置中心读取配置信息。以下是如何在 Spring Boot 中读取 Nacos 上的配置文件的步骤: 1. 引入依赖 首先,在 Spring Boot 项目的 pom.xml 文件中添加 …

Android Kotlin知识汇总(一)编程语言

在 2019 年 Google I/O 大会上宣布今后将优先采用 Kotlin 进行 Android 开发。Kotlin 是一种富有表现力且简洁的编程语言,不仅可以减少常见代码错误,还可以轻松集成到现有应用中。如果您想构建 Android 应用,建议您从 Kotlin 开始着手&#x…

分享axios+signalr简单封装示例

Ajax Axios Axios 是一个基于 promise 网络请求库,作用于node.js 和浏览器中。 它是 isomorphic 的(即同一套代码可以运行在浏览器和node.js中)。在服务端它使用原生 node.js http 模块, 而在客户端 (浏览端) 则使用 XMLHttpRequests。 从浏览器创建 XMLHttpReque…

MySQL-QA-异常问题及解决方案(持续更新)

MySQL-Q&A(持续更新) 1.1 PID文件找不到 问题描述 错误详情: ERROR!The server quit without updating PID file (/usr/local/mysql/data/localhost.localdomain.pid) 解决方案 首先排查配置文件,一般路径为:/etc/my.cnf 检查…

D2力扣滑动窗口系列

滑动窗口算法(Sliding Window): 滑动窗口算法(Sliding Window):在给定数组 / 字符串上维护一个固定长度或不定长度的窗口。可以对窗口进行滑动操作、缩放操作,以及维护最优解操作。 滑动操作&am…

【Ubuntu】gonme桌面的 gdm 和 lightdm 区别

总结:都可以 gdm: 【Gnome Display Manager】 完整,体积大 lightdm: 【Light Display Manager】 轻量

甜甜圈和贪吃蛇的后续

代码复现-项目复现 代码复现 云课五分钟-02第一个代码复现-终端甜甜圈C-CSDN博客 项目复现 云课五分钟-03第一个开源游戏复现-贪吃蛇-CSDN博客 不同的地图 加入班级和标识 循序渐进 这些案例都是来源网络,只是方便熟悉一下云课使用过程。 此部分学生掌握情况非…

OpenCV 图像的几何变换

一、图像缩放 1.API cv2.resize(src, dsize, fx0,fy0,interpolation cv2.INTER_LINEAR) 参数: ①src :输入图像 ②dsize:绝对尺寸 ③fx,fy:相对尺寸 ④interpolation:插值方法 2.代码演示 import cv2 …

携手亚信安慧AntDB,在数智化浪潮中乘风破浪

随着大数据时代的到来,对数据库的需求愈发强烈。在这一背景下,国产数据库逐渐崭露头角,亚信安慧AntDB作为重要的代表产品之一正积极参与到激烈的市场竞争中。亚信安慧AntDB不仅追求技术的革新和突破,同时也致力于满足用户日益增长…

AVCE - AV Evasion Craft Online 更新 8 种加载方式 - 过 WD 等

免责声明:本工具仅供安全研究和教学目的使用,用户须自行承担因使用该工具而引起的一切法律及相关责任。作者概不对任何法律责任承担责任,且保留随时中止、修改或终止本工具的权利。使用者应当遵循当地法律法规,并理解并同意本声明…