Java多线程系列(七):并发容器的原理,7大并发容器详解、及使用场景
之前谈过高并发编程系列:
高并发编程系列:4种常用Java线程锁的特点,性能比较、使用场景
高并发编程系列:CountDownLatch、Semaphore等4大并发工具类详解
高并发编程系列:4大JVM性能分析工具详解,及内存泄漏分析方案
高并发编程系列:ConcurrentHashMap的实现原理(JDK1.7和JDK1.8)
Java并发编程系列:深入详解Synchronized同步锁的底层实现
今天详细介绍并发容器的实现原理,与同步容器的区别等。
并发容器的由来
在Java并发编程中,经常听到Java集合类,同步容器、并发容器,那么他们有哪些具体分类,以及各自之间的区别和优劣呢?
只有把这些梳理清楚了,你才能真正掌握在高并发的环境下,正确使用好并发容器,我们先从Java集合类,同步容器谈起。
1.什么是同步容器
Java的集合容器框架中,主要有四大类别:List、Set、Queue、Map,大家熟知的这些集合类ArrayList、LinkedList、HashMap这些容器都是非线程安全的。
如果有多个线程并发地访问这些容器时,就会出现问题。因此,在编写程序时,在多线程环境下必须要求程序员手动地在任何访问到这些容器的地方进行同步处理,这样导致在使用这些容器的时候非常地不方便。
所以,Java先提供了同步容器供用户使用。
同步容器可以简单地理解为通过synchronized来实现同步的容器,比如Vector、Hashtable以及SynchronizedList等容器。
2.同步容器,主要的分类:
- Vector
- Stack
- HashTable
- Collections.synchronized方法生成
同步容器面临的问题
可以通过查看Vector,Hashtable等这些同步容器的实现代码,可以看到这些容器实现线程安全的方式就是将它们的状态封装起来,并在需要同步的方法上加上关键字synchronized。
这样做的代价是削弱了并发性,当多个线程共同竞争容器级的锁时,吞吐量就会降低。
例如: HashTable只要有一条线程获取了容器的锁之后,其他所有的线程访问同步函数都会被阻塞,因此同一时刻只能有一条线程访问同步函数。
因此为了解决同步容器的性能问题,所以才有了并发容器。
什么是并发容器
java.util.concurrent包中提供了多种并发类容器。
并发类容器是专门针对多线程并发设计的,使用了锁分段技术,只对操作的位置进行同步操作,但是其他没有操作的位置其他线程仍然可以访问,提高了程序的吞吐量。
采用了CAS算法和部分代码使用synchronized锁保证线程安全。
并发容器有哪些分类
1.ConcurrentHashMap
对应的非并发容器:HashMap
目标:代替Hashtable、synchronizedMap,支持复合操作
原理:JDK6中采用一种更加细粒度的加锁机制Segment“分段锁”,JDK8中采用CAS无锁算法。
2.CopyOnWriteArrayList
对应的非并发容器:ArrayList
目标:代替Vector、synchronizedList
原理:利用高并发往往是读多写少的特性,对读操作不加锁,对写操作,先复制一份新的集合,在新的集合上面修改,然后将新集合赋值给旧的引用,并通过volatile 保证其可见性,当然写操作的锁是必不可少的了。
3.CopyOnWriteArraySet
对应的非并发容器:HashSet
目标:代替synchronizedSet
原理:基于CopyOnWriteArrayList实现,其唯一的不同是在add时调用的是CopyOnWriteArrayList的addIfAbsent方法,其遍历当前Object数组,如Object数组中已有了当前元素,则直接返回,如果没有则放入Object数组的尾部,并返回。
4.ConcurrentSkipListMap
对应的非并发容器:TreeMap
目标:代替synchronizedSortedMap(TreeMap)
原理:Skip list(跳表)是一种可以代替平衡树的数据结构,默认是按照Key值升序的。
5.ConcurrentSkipListSet
对应的非并发容器:TreeSet
目标:代替synchronizedSortedSet
原理:内部基于ConcurrentSkipListMap实现
6.ConcurrentLinkedQueue
不会阻塞的队列
对应的非并发容器:Queue
原理:基于链表实现的FIFO队列(LinkedList的并发版本)
7.LinkedBlockingQueue、ArrayBlockingQueue、PriorityBlockingQueue
对应的非并发容器:BlockingQueue
特点:拓展了Queue,增加了可阻塞的插入和获取等操作
原理:通过ReentrantLock实现线程安全,通过Condition实现阻塞和唤醒
实现类:
- LinkedBlockingQueue:基于链表实现的可阻塞的FIFO队列
- ArrayBlockingQueue:基于数组实现的可阻塞的FIFO队列
- PriorityBlockingQueue:按优先级排序的队列
ConcurrentHashMap的实现
HashMap,Hashtable与ConcurrentHashMap都是实现的哈希表数据结构,在随机读取的时候效率很高。
Hashtable实现同步是利用synchronized关键字进行锁定的,其是针对整张哈希表进行锁定的,即每次锁住整张表让线程独占,在线程安全的背后是巨大的浪费。
ConcurrentHashMap和Hashtable主要区别就是围绕着锁的粒度进行区别以及如何区锁定。
上图中,左边是Hashtable的实现方式,可以看到锁住整个哈希表;而右边则是ConcurrentHashMap的实现方式,单独锁住每一个桶(segment).ConcurrentHashMap将哈希表分为16个桶(默认值),诸如get(),put(),remove()等常用操作只锁当前需要用到的桶,而size()才锁定整张表。
原来只能一个线程进入,现在却能同时接受16个写线程并发进入(写线程需要锁定,而读线程几乎不受限制)。
所以,才有了并发性的极大提升。
高并发编程,除了并发容器,还会涉及到并发工具类:CountDownLatch等,后续将详细的介绍并发工具类,以及ConcurrentHashMap的底层实现细节,不仅要知其然,还要知其所以然,这样才能更好的掌握好高并发编程。
你可能也喜欢:
- Java多线程系列(三):Java线程池的使用方式,及核心运行原理
- Java多线程系列(四):4种常用Java线程锁的特点,性能比较、使用场景
- Java多线程系列(八):ConcurrentHashMap的实现原理(JDK1.7和JDK1.8)
- Java多线程系列(一):最全面的Java多线程学习概述
- Java多线程系列(六):深入详解Synchronized同步锁的底层实现
- Java多线程系列(十):源码剖析AQS的实现原理
Java多线程系列(七):并发容器的原理,7大并发容器详解、及使用场景相关推荐
- Java多线程系列七——ExecutorService
java.util.concurrent.ExecutorService接口提供了许多线程管理的方法 Method 说明 shutdown 拒绝接收新的任务,待已提交的任务执行后关闭,且宿主线程不阻塞 ...
- 【Java多线程系列七】ExecutorService
java.util.concurrent.ExecutorService接口提供了许多线程管理的方法 Method 说明 shutdown 拒绝接收新的任务,待已提交的任务执行后关闭,且宿主线程不阻塞 ...
- Java基础学习总结(33)——Java8 十大新特性详解
Java8 十大新特性详解 本教程将Java8的新特新逐一列出,并将使用简单的代码示例来指导你如何使用默认接口方法,lambda表达式,方法引用以及多重Annotation,之后你将会学到最新的API ...
- Java多线程系列(九):CountDownLatch、Semaphore等4大并发工具类详解
之前谈过高并发编程系列:4种常用Java线程锁的特点,性能比较.使用场景 ,以及高并发编程系列:ConcurrentHashMap的实现原理(JDK1.7和JDK1.8) 今天主要介绍concurre ...
- Java多线程系列(五):线程池的实现原理、优点与风险、以及四种线程池实现
为什么需要线程池 我们有两种常见的创建线程的方法,一种是继承Thread类,一种是实现Runnable的接口,Thread类其实也是实现了Runnable接口.但是我们创建这两种线程在运行结束后都会被 ...
- Java多线程系列(十):源码剖析AQS的实现原理
在并发编程领域,AQS号称是并发同步组件的基石,很多并发同步组件都是基于AQS实现,所以想掌握好高并发编程,你需要掌握好AQS. 本篇主要通过对AQS的实现原理.数据模型.资源共享方式.获取锁的过程, ...
- Java多线程系列(六):深入详解Synchronized同步锁的底层实现
谈到多线程就不得不谈到Synchronized,很多同学只会使用,缺不是很明白整个Synchronized的底层实现原理,这也是面试经常被问到的环节,比如: synchronized的底层实现原理 s ...
- Java多线程系列(二):线程的五大状态,以及线程之间的通信与协作
在Java面试的时候,经常会问到Java并发编程相关的多线程.线程池.线程锁.线程通信等面试必考点,比如: Java并发编程系列:Java线程池的使用方式,核心运行原理.以及注意事项 Java并发编程 ...
- java多线程系列(四)---ReentrantLock的使用
Lock的使用 前言:本系列将从零开始讲解java多线程相关的技术,内容参考于<java多线程核心技术>与<java并发编程实战>等相关资料,希望站在巨人的肩膀上,再通过我的理 ...
最新文章
- 【转摘】Word提升效率的快捷键
- [渝粤教育] 中国地质大学 婚姻与家庭法 复习题
- 第一章 计算机系统概述 1.3 计算机的性能指标 [计算机组成原理笔记]
- 第四届CocoaChina开发者大会官网上线
- Linux下vsftpd基本配置和虚拟用户设置的安全方法
- 宁德时代,想成为“绿巨人”
- 正则表达式 re模块
- unity3d 材质概述 ---- shader
- L1-012 计算指数 (5 分)—团体程序设计天梯赛
- 在Winform中实现半透明遮罩层
- fw325r没有虚拟服务器,迅捷fw325r路由器设置完没有网怎么办?
- python 百度cpc点击
- 什么是pisa测试_PISA测试很专业,但对理解什么是教育很重要
- 记一次Spark中 Container killed by YARN for exceeding memory limits的解决过程
- 学生管理系统(大数据实验室)
- buuctf pwn wp(第四波)格式化字符串漏洞系列
- 思杰虚拟服务器退出管理主机,思杰服务器虚拟化解决详尽方案介绍2012.ppt
- Vue文件上传、下载
- mysql 快照_Mysql可重复读(2) —— 快照真的就是快照吗
- 《计算机网络》课程小程序的设计与实现 报告+项目源码+部署教程
热门文章
- .NET下使用DataAdapter保存数据时,如何生成command语句及使用事务
- 尘埃落定,初心未改——一个大学生的电子大赛感悟
- 别瞎找了,你要的C语言经典示例都在这~
- sizeof你真的弄明白了吗?
- 51单片机——UART
- php无法创建cookie,php-curl cookie无法成功创建
- bufg和bufgp_如何将自己写的verilog模块封装成IP核(一)
- 视频操作_02视频追踪:meanshift算法+Camshift算法
- 数据结构之堆:堆的排序,Python代码实现——13
- pythonfor循环列表排序_Python Day4950(for循环语句整理)