【JavaEE】线程安全的集合类

作者主页:paper jie_博客

本文作者:大家好,我是paper jie,感谢你阅读本文,欢迎一建三连哦。

本文于《JavaEE》专栏,本专栏是针对于大学生,编程小白精心打造的。笔者用重金(时间和精力)打造,将基础知识一网打尽,希望可以帮到读者们哦。

其他专栏:《MySQL》《C语言》《javaSE》《数据结构》等

内容分享:本期将会分享线程安全的集合类芝士

目录

引入

多线程使用ArrayList

多线程使用队列

多线程使用哈希表

Hashtable

ConcurrentHashMap

相关面试题


引入

之前我们所学的集合类,大多数都是线程不安全的.,像ArrayList,LinkedList,Queue等都是线程不安全的.这里我们将介绍`线程安全的类

多线程使用ArrayList

1.可以自己使用synchronized来加锁实现线程安全

2.Collections.synchronizedList(new ArrayList);

它就相当于给ArrayList套了一个壳,通过这个壳得到了一个新的对象,这个新的对象的关键方法就加上了synchronized.

3.使用CopyOnWritArrayList

当我们放容器中添加元素时,不会往旧容器中添加,而是会将当前这个容器的数据拷贝到一个新的容器中.添加完元素后,在将原有容器的引用指向新的容器.

它带来的好处就是我们可以对CopyWritArrayList容器进行并发的读,不需要加锁,因为当前容器不会添加任何元素.

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

缺点就是比较占用内存,新写的数据不能第一时间读到.且不适用与写多的场景.

多线程使用队列

1.ArrayListBlockingQueue

2.LinkedListBlockingQue

3.priorityBlockingQueue

4.TransferQueue

只包含一个元素的阻塞队列.

多线程使用哈希表

Hashtable

在数据结构中,我们学过hashmap和hashset,这两者本身其实是线程不安全的.在所线程的环境下我们就可以使用Hashable和CouncurrentHashMap.

而我们的Hashtable就是在关键方法中加上了synchronized关键字,这其实就是直接对Hashtable对象本身直接加锁.这就会出现一些问题:

如果多个线程访问同一个Hashtable就会造成锁冲突.

size属性也是被synchronized控制,这样锁冲突会进一步加大.

一但触发扩容,就会由该线程来完成扩容过程,这个过程机会涉及到大量的元素拷贝,这里的速度就会很慢.

一个Hashtable就只有一个锁,只要有两个线程访问这个HashTable中的任意一个数据就会发生锁竞争.这里读操作和其他链表的元素是不会发生线程安全问题的,但是这里还是会有锁.

ConcurrentHashMap

相比于Hashtable,ConcurrentHashMap就做出了一系列的改进和优化.这里以Java1.8为例:

1. 读操作没有加锁,只是使用了volatile保证从内存读取结果,只对写操作进行加锁.加锁的方式仍然是使用synchronized,只不过它加锁的不是整个对象,而是"锁桶",这就是每一个链表,这里用每个链表的头节点来作为锁对象,这样就大大降低了锁冲突的概率.

2. 充分的利用了CAS特性.size属性就是使用CAS来更新的,这样就又降低了锁冲突的概率.

3. 优化了扩容方法,采用的是化整为零.

发现需要扩容的线程,只需要创建出一个数组,再搬运少量元素过去即可.

扩容期间,新老数组同时存在

后面每个操作ConcurrentMap的线程都会参与搬运数组的任务,每个操作都会搬运一小部分

直到搬运完最后一个元素再将老数组删除.

这个期间插入元素只往新数组中插入.

这个期间查找删除元素新数组和老数组都需要查找和删除.

相关面试题

  1. ConcurrentHashMap的读是否要加锁?

读不需要加锁,这样可以减少锁冲突.但是为了及时读到刚修改的数据,搭配了volatile关键字.

  1. 介绍ConcurrentHashMap的分段技术?

这是Java1.7中采用的技术.Java1.8中已经不再使用了.它就是将若干个链表分成一个段,给段加上锁,目的还是为了降低锁竞争的概率.当两个线程访问的数据在一个段中就会发生锁竞争.

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

取消了分段锁,直接给每个哈希桶每个链表分配了一个锁.将原来数组+链表的实现方式改变为数组+链表+红黑树的方式.当链表大于等于8时就会由链表转变为红黑树.

4.Hashtable和HashMap,ConcurrentHashMap的区别?

HashMap: 线程不安全,key可以为null

Hashtable: 线程安全,使用synchronized锁加在Hashtable对象上,效率低.且key不可以为null

ConcurrentHashMap: 线程安全,使用synchronized锁加在每个链表上,锁冲突率低,充分利用CAS机制,优化了扩容方式,key不能为null.

相关推荐
古希腊掌管学习的神19 分钟前
[LeetCode-Python版]相向双指针——611. 有效三角形的个数
开发语言·python·leetcode
赵钰老师19 分钟前
【R语言遥感技术】“R+遥感”的水环境综合评价方法
开发语言·数据分析·r语言
V+zmm1013425 分钟前
基于微信小程序的乡村政务服务系统springboot+论文源码调试讲解
java·微信小程序·小程序·毕业设计·ssm
就爱学编程27 分钟前
重生之我在异世界学编程之C语言小项目:通讯录
c语言·开发语言·数据结构·算法
Oneforlove_twoforjob1 小时前
【Java基础面试题025】什么是Java的Integer缓存池?
java·开发语言·缓存
emoji1111111 小时前
前端对页面数据进行缓存
开发语言·前端·javascript
xmh-sxh-13141 小时前
常用的缓存技术都有哪些
java
每天都要学信号1 小时前
Python(第一天)
开发语言·python
TENET信条1 小时前
day53 第十一章:图论part04
开发语言·c#·图论
生信圆桌1 小时前
【生信圆桌x教程系列】如何安装 seurat V5版本R包,最详细安装手册
开发语言·r语言