Java并发包中常用类
Java并发包中常用类小结(一)
从JDK1.5以后,Java为我们引入了一个并发包,用于解决实际开发中经常用到的并发问题,那我们今天就来简单看一下相关的一些常见类的使用情况。
1、ConcurrentHashMap
ConcurrentHashMap其实就是线程安全版本的hashMap。前面我们知道HashMap是以链表的形式存放hash冲突的数据,以数组形式存放HashEntry等hash出来不一致的数据。为了保证容器的数据一致性,需要加锁。HashMap的实现方式是,只有put和remove的时候会引发数据的不一致,那为了保证数据的一致性,我在put和remove的时候进行加锁操作。但是随之而来的是性能问题,因为key-value形式的数据,读写频繁是很正常的,也就意味着我有大量数据做读写操作时会引发长时间的等待。为了解决这个问题,Java并发包问我们提供了新的思路。在每一个HashEntry上加一把锁,对于hash冲突的数据,因为采用链表存储,公用一把锁。这样我才在做不同hash数值的数据时,则是在不同的锁环境下执行,基本上是互不干扰的。在最好情况下,可以保证16个线程同时进行无阻塞的操作(HashMap的默认HashEntry是16,亦即默认的数组大小是16)。
那ConcurrentHashMap是如何保证数据操作的一致性呢?对于数据元素的大小,ConcurrentHashMap将对应数组(HashEntry的长度)的变量为voliate类型的,也就是任何HashEntry发生变更,所有的地方都会知道数据的大小。对于元素,如何保证我取出的元素的next不发生变更呢?(HashEntry中的数据采用链表存储,当读取数据的时候可能又发生了变更),这一点,ConcurrentHashMap采取了最简单的做法,hash值、key和next取出后都为final类型的,其next等数据永远不会发生变更。
另外ConcurrentHashMap采用的锁结构是将读和写分开的,大大的提升了性能,下面我们来看一下两者之间的性能差。
由于数据比较密集,我们分开来看一下
相关数据如下:
分析表 |
元素个数 |
10 |
100 |
1000 |
10000 |
||||||||
线程数 |
容器类别 |
增加 |
删除 |
查找 |
增加 |
删除 |
查找 |
增加 |
删除 |
查找 |
增加 |
删除 |
查找 |
1 |
HashMap |
2805 |
1743 |
1520 |
3004 |
1726 |
1579 |
1995 |
1846 |
1528 |
2032 |
1787 |
1501 |
ConcurrentHashMap |
4947 |
2010 |
1699 |
5292 |
2005 |
1661 |
2322 |
1842 |
1243 |
2351 |
2113 |
1541 |
|
10 |
HashMap |
29814 |
36539 |
28076 |
31180 |
55178 |
38156 |
31217 |
36756 |
31785 |
33314 |
30497 |
26488 |
ConcurrentHashMap |
18364 |
22086 |
8064 |
21420 |
22805 |
9932 |
20164 |
20875 |
7800 |
19383 |
19483 |
10254 |
|
50 |
HashMap |
233674 |
193918 |
230404 |
205577 |
221995 |
213651 |
343005 |
318603 |
343153 |
249921 |
229954 |
234555 |
ConcurrentHashMap |
131573 |
98534 |
16778 |
152609 |
96412 |
24233 |
123199 |
108388 |
20156 |
134971 |
122927 |
18799 |
|
100 |
HashMap |
313442 |
309336 |
302591 |
332389 |
314167 |
296360 |
343005 |
318603 |
343153 |
329171 |
352704 |
354593 |
ConcurrentHashMap |
161866 |
122582 |
21369 |
141274 |
114333 |
21875 |
116758 |
97985 |
24098 |
140902 |
120459 |
18766 |
(神马情况 数据看不到了 弄一个图吧)
我们可以看到,在单线程下,ConcurrentHashMap的综合性能略低于HashMap,但是随着线程的增长,ConcurrentHashMap的优势就明显提现出来了,尤其是查找元素的性能。因此并发情况下,ConcurrentHashMap是代替HashMap的一个不错的选择。
2、CopyOnWriteArrayList
同样的,CopyOnWriteArrayList是线程安全版本的ArrayList。和ArrayList不同的是,CopyOnWriteArrayList默认是创建了一个大小为0的容器。通过ReentrantLock来保证线程安全。CopyOnWriteArrayList其实每次增加的时候,需要新创建一个比原来容量+1大小的数组,然后拷贝原来的元素到新的数组中,同时将新插入的元素放在最末端。然后切换引用。
针对CopyOnWriteArrayList,因为每次做插入和删除操作,都需要重新开辟空间和复制数组元素,因此对于插入和删除元素,CopyOnWriteArrayList的性能远远不如ArrayList,但是每次读取的时候,CopyOnWriteArrayList在不加锁的情况下直接锁定数据,会快很多(但是可能会引发脏读),对于迭代,CopyOnWriteArrayList会生成一个快照数组,因此当迭代过程中出现变化,快照数据没有变更,因此读到的数据也是不会变化的。在读多写少的环境下,CopyOnWriteArrayList的性能还是不错的。
3、CopyOnWriteArraySet
CopyOnWriteArraySet是基于CopyOnWriteArrayList实现的。但是CopyOnWriteArraySet鉴于不能插入重复数据,因此每次add的时候都要遍历数据,性能略低于CopyOnWriteArrayList。
4、ArrayBlockingQueue
ArrayBlockingQueue是基于数组实现的一个线程安全的队列服务,其相关的功能前面我们已经用到过了,这里就不多提了。
5、Atomic类,如AtomicInteger、AtomicBoolean
我们来看以下对应的API文档
这种原子类是基于JDK的CAS的无阻塞操作,比我们写同步的效率要高多了哦。
对于Atomic类我们在后面的示例中也会很频繁的使用,这里也就不多介绍了。
Java并发包中常用类相关推荐
- Java并发包中常用类小结(一)
Java并发包中常用类小结(一) 从JDK1.5以后,Java为我们引入了一个并发包,用于解决实际开发中经常用到的并发问题,那我们今天就来 ...
- java并发编程中常用的工具类 Executor
/*************************************************** * TODO: description . * @author: gao_chun * ...
- 详解Java多线程编程中LockSupport类的线程阻塞用法
转载自 详解Java多线程编程中LockSupport类的线程阻塞用法 LockSupport类是Java6(JSR166-JUC)引入的一个类,提供了基本的线程同步原语.LockSupport实际 ...
- 第 5-6 课:Java 并发包中的高级同步工具 + 面试题
Java 中的并发包指的是 java.util.concurrent(简称 JUC)包和其子包下的类和接口,它为 Java 的并发提供了各种功能支持,比如: 提供了线程池的创建类 ThreadPool ...
- java零基础Ⅱ-- 4.常用类
java零基础Ⅱ-- 4.常用类 一.包装类 包装类的分类 包装类和基本数据的转换 演示 测试题 包装类型和String类型的相互转换 Integer类和Character类的常用方法 Integer ...
- java 8 Stream中操作类型和peek的使用
文章目录 简介 中间操作和终止操作 peek 结论 java 8 Stream中操作类型和peek的使用 简介 java 8 stream作为流式操作有两种操作类型,中间操作和终止操作.这两种有什么区 ...
- Java遍历包中所有类包括jar包(完整转载)
第一部分转自 :http://blog.csdn.net/wangpeng047/article/details/8124390 第二部分转自:http://blog.csdn.net/wangpen ...
- Java遍历包中所有类
由于项目需要,我想获得某包下所有的类(包括该包的所有子包),从网上找了找,没有什么能用的,即使找到了写的也不怎样,效率低下.索性就自己写吧,正好也锻炼锻炼写代码的功底.特此分享出来,希望能帮到大家.. ...
- Java遍历包中所有类-终续
上一篇中,我向大家讲述了遍历jar包时所遇到的困难,本篇将向大家分享最终版代码. package com.itkt.mtravel.hotel.util;import java.io.File; im ...
最新文章
- 科技股疯狂造富的背后,“泡沫”离我们到底有多远?
- easyUI menu动态添加
- 2021-07-09
- 动态游标(例如表名作为参数)以及动态SQL分析
- mysql5.6.39的安装_如何安装MySQL Community Server 5.6.39
- python3安装pip3的方法
- js split参数为无效字符_互联网前端开发技术JavaScript字符串类型详解
- Atitit 获取一列拼接为字符串 逗号分隔 目录1.1. Sql Group_contackt,但是排序只能拍一个的。。如果多个列对应排序则不行。。。 11.2. Js 使用map函数 1
- KaTeX|LaTeX数学公式编辑手册
- 对.gpx文件进行地图坐标系转换
- Stata | 导入导出文件
- 软件开发生命周期的四个阶段
- PTA:7-120 新浪微博热门话题 (30分)--(map方法,加解析)
- 乡镇特色产业发展调研报告2
- ZPanel-开源免费的虚拟主机在线管理系统
- java能否构成三角形_java中判断三个参数是否能构成三角形的方法
- 【观察】四川产业转型“加速跑”,鲲鹏生态助推“新升级”
- 透明、反光材质护肤品拍摄技巧
- SessionFactory的创建和Session的获得
- 经纬度转换为UTM坐标