美文网首页
Java并发容器和框架

Java并发容器和框架

作者: ShayHe | 来源:发表于2020-02-05 09:42 被阅读0次

1.ConcurrentHashMap 的实现原理与使用

  ConcurrentHashMap是线程安全高效的HashMap。本节让我们一起研究一下该容器是如何在保证线程安全的同时又能保证高效的操作。
1.1 为什么要使用ConcurrentHashMap
  在并发编程中HashMap可能导致程序死循环。而使用线程安全的HashTable效率又非常低下,基于以上两个原因,便有了ConcurrentHashMap的登场机会。
  (1)线程不安全的HashMap
  在多线程环境下,使用HashMap进行put操作会引起死循环、导致CPU利用率接近100%,所以在并发情况下不能使用HashMap。

final HashMap<String, String> map = new HashMap<>(2);
        Thread t = new Thread(() -> {
            for(int i=0;i<10000;i++){
                new Thread(() -> map.put(UUID.randomUUID().toString(), ""),"ftf"+i).start();
            }
        },"ftf");
        t.start();
        t.join();

  HashMap 在并发执行put操作时会引起死循环,是因为多线程会导致HashMap的Entry链表形成环形数据结构,一旦形成环形数据结构,Entry的next节点永远不为空,就会产生链表形成环形数据。
  (2)效率低下的HashTable
  HashTable容器使用synchronized来保证线程安全,但在线程竞争激烈情况下Hash Table的效率非常低下 。因为当一个线程访问HashTable的同步方法, 其他线程也 访问Hash Table的同步方法时, 会进入阻塞或轮询状态。如线程l使用put 进行元素添加, 线程 2不但不能使用put方法添加元素, 也不能使用get方法来获取元素, 所以 竞争越激烈 效率越低。
  (3)ConcurrentHashMap的锁分段技术可有效提升并发率
  Hash Table容器在竞争激烈的并发环境下表现出效率低下的原因是所 有访问HashTable的线程都必须竞争同一把锁,假如容器里有多把锁,每一把锁用于锁容器其中一部分数据,那么当多线程访问容器里不同数据段的数据时,线程间就不会存在锁竞争,从而可以有效提高并发访问效率,这就是ConcurrentHashMap所使用的锁分段技术。首先将数据分成一段一段地存储,然后给每一段数据配一把锁,当一个线程占用锁访问其中一个段数据的时候,其他段的数据也能被其他线程访问。
1.2 ConcurrentHashMap 的结构
  ConcurrentHashMap是由Segment 数组 结构和HashEntry数组结构组 成。Segment是 一种可重人锁( ReentrantLock),在ConcurrentHashMap里扮演锁的角色;HashEntry则用于存储键值对数据。一个ConcurrentHashMap里包含一 个Segment 数组 。Segment的结构和HashMap 类似,是一种数组 和链表结构。一 个Segment里包含一 个HashEntry数组,每个HashEntry是一个链表结构的元素,每个Segment守护着一 个HashEntry数组里的元素,当对HashEntry数组的数据进行修改时,必须首先获得与它对应的Segment 锁。
1.3 ConcurrentHashMap 的初始化
  ConcurrentHashMap 初始化方法是通过 initialCapacity、 loadFactor 和 concurrencyLevel 等几个参数来初始化 segment 数组、 段偏移量 segmentShift,段掩码 segmentMask 和每个 segment 里的 HashEntry数组来实现的。

2. ConcurrentLinkedQueue

  ConcurrentLinkedQueue囱head节点和tail节点组成, 每个节点( Node)由节点元素(item)和指向下一个节点(next)的引用组成,节点与节点之间就是通过这个 next关联起来, 从而组成一张链表结构的队列。 默认情况下head节点存储的元素为空,tail节点等于head 节点。

3. Java中的阻塞队列

3.1 阻塞队列的定义
  阻塞队列(BlockingQueue)是一个支持两个附加操作的队列。这两个附加的操作支持阻塞的插入和移除方法。
3.2 Java 里的阻塞队列

7个阻塞队列.png

相关文章

网友评论

      本文标题:Java并发容器和框架

      本文链接:https://www.haomeiwen.com/subject/pqddxhtx.html