纯净、安全、绿色的下载网站

首页|软件分类|下载排行|最新软件|IT学院

当前位置:首页IT学院IT技术

Java并发容器 Java并发容器相关知识总结

Java_maxiaoyi   2021-06-06 我要评论
想了解Java并发容器相关知识总结的相关内容吗Java_maxiaoyi在本文为您仔细讲解Java并发容器的相关知识和一些Code实例欢迎阅读和指正我们先划重点:Java并发容器,java容器下面大家一起来学习吧。

一、并发容器

1.1 JDK 提供的并发容器总结

JDK 提供的这些容器大部分在java.util.concurrent包中。

ConcurrentHashMap: 线程安全的 HashMap

CopyOnWriteArrayList: 线程安全的 List在读多写少的场合性能非常好,远远好于 Vector.

ConcurrentLinkedQueue: 高效的并发队列使用链表实现。可以看做一个线程安全的

LinkedList这是一个非阻塞队列。

BlockingQueue: 这是一个接口JDK 内部通过链表、数组等方式实现了这个接口。表示阻塞队列非常适合用于作为数据共享的通道。

ConcurrentSkipListMap: 跳表的实现。这是一个 Map使用跳表的数据结构进行快速查找。

1.2 ConcurrentHashMap

我们知道 HashMap 不是线程安全的在并发场景下如果要保证一种可行的方式是使用
Collections.synchronizedMap()方法来包装我们的 HashMap。但这是通过使用一个全局的锁来同步不同线程间的并发访问因此会带来不可忽视的性能问题。

所以就有了 HashMap 的线程安全版本—— ConcurrentHashMap 的诞生。在 ConcurrentHashMap 中无论是读操作还是写操作都能保证很高的性能:在进行读操作时(几乎)不需要加锁而在写操作时 通过锁分段技术只对所操作的段加锁而不影响客户端对其它段的访问。

1.3 CopyOnWriteArrayList

1.3.1 CopyOnWriteArrayList 简介

Java并发容器讲解

在很多应用场景中读操作可能会远远大于写操作。由于读操作根本不会修改原有的数据因此对于每 次读取都进行加锁其实是一种资源浪费。我们应该允许多个线程同时访问 List 的内部数据毕竟读取操作是安全的。

这和我们之前在多线程章节讲过 ReentrantReadWriteLock 读写锁的思想非常类似也就是读读共享、写写互斥、读写互斥、写读互斥。JDK 中提供了 CopyOnWriteArrayList 类比相比于在读写锁的思想又更进一步。为了将读取的性能发挥到极致 CopyOnWriteArrayList 读取是完全不用加锁的 并且更厉害的是:写入也不会阻塞读取操作。只有写入和写入之间需要进行同步等待。这样一来读操 作的性能就会大幅度提升。那它是怎么做的呢?

1.3.2 CopyOnWriteArrayList 是如何做到的?

Java并发容器讲解

1.3.3 CopyOnWriteArrayList 读取和写入源码简单分析

1.3.3.1 CopyOnWriteArrayList 读取操作的实现

读取操作没有任何同步控制和锁操作理由就是内部数组 array 不会发生修改只会被另外一个 array替换因此可以保证数据安全。

Java并发容器讲解

1.3.3.2 CopyOnWriteArrayList 写入操作的实现

CopyOnWriteArrayList 写入操作 add() 方法在添加集合的时候加了锁保证了同步避免了多线程写的时候会 copy 出多个副本出来。

Java并发容器讲解

1.4 ConcurrentLinkedQueue

Java并发容器讲解

1.5 BlockingQueue

1.5.1 BlockingQueue 简单介绍

上面我们己经提到了 ConcurrentLinkedQueue 作为高性能的非阻塞队列。下面我们要讲到的是阻塞队列——BlockingQueue。阻塞队列(BlockingQueue)被广泛使用在“生产者-消费者”问题中其原因是BlockingQueue 提供了可阻塞的插入和移除的方法。当队列容器已满生产者线程会被阻塞直到队列未满;当队列容器为空时消费者线程会被阻塞直至队列非空时为止。

BlockingQueue 是一个接口继承自 Queue所以其实现类也可以作为 Queue 的实现来使用而Queue 又继承自 Collection 接口。下面是 BlockingQueue 的相关实现类:

Java并发容器讲解

下面主要介绍一下:ArrayBlockingQueue、LinkedBlockingQueue、PriorityBlockingQueue这三个 BlockingQueue 的实现类。

1.5.2 ArrayBlockingQueue

Java并发容器讲解

 Java并发容器讲解

1.5.3 LinkedBlockingQueue

LinkedBlockingQueue 底层基于单向链表实现的阻塞队列可以当做无界队列也可以当做有界队列来使用同样满足 FIFO 的特性与 ArrayBlockingQueue 相比起来具有更高的吞吐量为了防止LinkedBlockingQueue 容量迅速增损耗大量内存。通常在创建 LinkedBlockingQueue 对象时会指定其大小如果未指定容量等于 Integer.MAX_VALUE。

相关构造方法:

Java并发容器讲解

1.5.4 PriorityBlockingQueue

Java并发容器讲解

1.6 ConcurrentSkipListMap

为了引出 ConcurrentSkipListMap先带着大家简单理解一下跳表。

对于一个单链表即使链表是有序的如果我们想要在其中查找某个数据也只能从头到尾遍历链表 这样效率自然就会很低跳表就不一样了。跳表是一种可以用来快速查找的数据结构有点类似于平衡树。它们都可以对元素进行快速地查找。但一个重要的区别是:对平衡树的插入和删除往往很可能导致 平衡树进行一次全局的调整。而对跳表的插入和删除只需要对整个数据结构的局部进行操作即可。这样 带来的好处是:在高并发的情况下你会需要一个全局锁来保证整个平衡树的线程安全。而对于跳表 你只需要部分锁即可。这样在高并发环境下你就可以拥有更好的性能。而就查询的性能而言跳表的时间复杂度也是 O(logn) 所以在并发数据结构中JDK 使用跳表来实现一个 Map。

跳表的本质是同时维护了多个链表并且链表是分层的

Java并发容器讲解

最低层的链表维护了跳表内所有的元素每上面一层链表都是下面一层的子集。

跳表内的所有链表的元素都是排序的。查找时可以从顶级链表开始找。一旦发现被查找的元素大于当前链表中的取值就会转入下一层链表继续找。这也就是说在查找过程中搜索是跳跃式的。如上图所示在跳表中查找元素 18。

Java并发容器讲解

查找 18 的时候原来需要遍历 18 次现在只需要 7 次即可。针对链表长度比较大的时候构建索引查找效率的提升就会非常明显。

从上面很容易看出跳表是一种利用空间换时间的算法。

使用跳表实现 Map 和使用哈希算法实现 Map 的另外一个不同之处是:哈希并不会保存元素的顺序而跳表内所有的元素都是排序的。因此在对跳表进行遍历时你会得到一个有序的结果。所以如果你的应用需要有序性那么跳表就是你不二的选择。JDK 中实现这一数据结构的类是ConcurrentSkipListMap。


相关文章

猜您喜欢

  • java适配器模式 java设计模式之浅谈适配器模式

    想了解java设计模式之浅谈适配器模式的相关内容吗RYGAR在本文为您仔细讲解java适配器模式的相关知识和一些Code实例欢迎阅读和指正我们先划重点:java适配器模式,java设计模式下面大家一起来学习吧。..
  • Java桥接模式 Java设计模式之桥接模式的实现

    想了解Java设计模式之桥接模式的实现的相关内容吗RYGAR在本文为您仔细讲解Java桥接模式的相关知识和一些Code实例欢迎阅读和指正我们先划重点:Java桥接模式,java设计模式下面大家一起来学习吧。..

网友评论

Copyright 2020 www.Shellfishsoft.com 【贝软下载站】 版权所有 软件发布

声明:所有软件和文章来自软件开发商或者作者 如有异议 请与本站联系 点此查看联系方式