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并发包中常用类相关推荐

  1. Java并发包中常用类小结(一)

                                   Java并发包中常用类小结(一) 从JDK1.5以后,Java为我们引入了一个并发包,用于解决实际开发中经常用到的并发问题,那我们今天就来 ...

  2. java并发编程中常用的工具类 Executor

    /***************************************************  * TODO: description .  * @author: gao_chun  * ...

  3. 详解Java多线程编程中LockSupport类的线程阻塞用法

    转载自  详解Java多线程编程中LockSupport类的线程阻塞用法 LockSupport类是Java6(JSR166-JUC)引入的一个类,提供了基本的线程同步原语.LockSupport实际 ...

  4. 第 5-6 课:Java 并发包中的高级同步工具 + 面试题

    Java 中的并发包指的是 java.util.concurrent(简称 JUC)包和其子包下的类和接口,它为 Java 的并发提供了各种功能支持,比如: 提供了线程池的创建类 ThreadPool ...

  5. java零基础Ⅱ-- 4.常用类

    java零基础Ⅱ-- 4.常用类 一.包装类 包装类的分类 包装类和基本数据的转换 演示 测试题 包装类型和String类型的相互转换 Integer类和Character类的常用方法 Integer ...

  6. java 8 Stream中操作类型和peek的使用

    文章目录 简介 中间操作和终止操作 peek 结论 java 8 Stream中操作类型和peek的使用 简介 java 8 stream作为流式操作有两种操作类型,中间操作和终止操作.这两种有什么区 ...

  7. Java遍历包中所有类包括jar包(完整转载)

    第一部分转自 :http://blog.csdn.net/wangpeng047/article/details/8124390 第二部分转自:http://blog.csdn.net/wangpen ...

  8. Java遍历包中所有类

    由于项目需要,我想获得某包下所有的类(包括该包的所有子包),从网上找了找,没有什么能用的,即使找到了写的也不怎样,效率低下.索性就自己写吧,正好也锻炼锻炼写代码的功底.特此分享出来,希望能帮到大家.. ...

  9. Java遍历包中所有类-终续

    上一篇中,我向大家讲述了遍历jar包时所遇到的困难,本篇将向大家分享最终版代码. package com.itkt.mtravel.hotel.util;import java.io.File; im ...

最新文章

  1. 科技股疯狂造富的背后,“泡沫”离我们到底有多远?
  2. easyUI menu动态添加
  3. 2021-07-09
  4. 动态游标(例如表名作为参数)以及动态SQL分析
  5. mysql5.6.39的安装_如何安装MySQL Community Server 5.6.39
  6. python3安装pip3的方法
  7. js split参数为无效字符_互联网前端开发技术JavaScript字符串类型详解
  8. Atitit 获取一列拼接为字符串 逗号分隔 目录1.1. Sql Group_contackt,但是排序只能拍一个的。。如果多个列对应排序则不行。。。 11.2. Js 使用map函数 1
  9. KaTeX|LaTeX数学公式编辑手册
  10. 对.gpx文件进行地图坐标系转换
  11. Stata | 导入导出文件
  12. 软件开发生命周期的四个阶段
  13. PTA:7-120 新浪微博热门话题 (30分)--(map方法,加解析)
  14. 乡镇特色产业发展调研报告2
  15. ZPanel-开源免费的虚拟主机在线管理系统
  16. java能否构成三角形_java中判断三个参数是否能构成三角形的方法
  17. 【观察】四川产业转型“加速跑”,鲲鹏生态助推“新升级”
  18. 透明、反光材质护肤品拍摄技巧
  19. SessionFactory的创建和Session的获得
  20. 经纬度转换为UTM坐标

热门文章

  1. PHP获取客户端和服务器端IP
  2. linux光标变成圆圈,Ubuntu字体美化之安装使用准圆字体(附图)
  3. mysql之sql语句优化
  4. Telegraf介绍和使用
  5. 安卓学习笔记5.3 按钮、图像视图与图像按钮
  6. USB Type-C简介
  7. 两张(多张)图片合成一张图片
  8. python多维字典_python定义多维字典
  9. 微信小程序从开发到上线步骤(持续更新)
  10. 2022年Roguelike“割草”游戏风潮为何刮的如此强劲?