zoukankan      html  css  js  c++  java
  • 高并发下用的容器类

    参考博客:https://www.cnblogs.com/daoqidelv/p/6753162.html

    java cocurrent包提供了很多并发容器,在提供并发控制的前提下,通过优化,提升性能

    为什么JUC需要提供并发容器?

    1. java.util包中的大部分容器都是非线程安全的,若要在多线程中使用容器,你可以使用Collections提供的包装函数:synchronizedXXX,将普通容器变成线程安全的容器。但该方法仅仅是简单地给容器使用同步,效率很低。因此并发大师Doug Lea提供了java.util.concurrent包,提供高效的并发容器。并且为了保持与普通的容器的接口一致性,仍然使用util包的接口,从而易于使用、易于理解。

    2.使用工具类Collections将非线程安全容器包装成线程安全容器。以下代码是Collections.synchronizedMap(Map<K,V> m)将原始Map包装为线程安全的SynchronizedMap,但是实际上最终操作时,仍然是在被包装的原始m上进行,只是SynchronizedMap的所有方法都加上了synchronized锁控制。

    为了提供高效地并发容器,java 5在java.util.cocurrent包中 引入了并发容器。

    JUC并发容器

    本节对juc常用的几个并发容器进行代码分析,重点看下这些容器是如何高效地实现并发控制的。在进行具体的并发容器介绍之前,我们提前搞清楚CAS理论是什么东西。因为在juc并发容器的很多地方都使用到了CAS,他比加锁处理更加高效

    CAS

    CAS是一种无锁的非阻塞算法,全称为:Compare-and-swap(比较并交换),大致思路是:先比较目标对象现值是否和旧值一致,如果一致,则更新对象为新值;如果不一致,则表明对象已经被其他线程修改,直接返回。算法实现的伪码如下:

    function cas(p : pointer to int, old : int, new : int) returns bool {
        if *p ≠ old {
            return false
        }
        *p ← new
        return true
    }

    List和Set

    JUC包中List接口的实现类:CopyOnWriteArrayList

    CopyOnWriteArrayList是线程安全的ArrayList

    CopyOnWriteArrayList提供高效地读取操作,使用在读多写少的场景。CopyOnWriteArrayList读取操作不用加锁,且是安全的;写操作时,先copy一份原有数据数组,再对复制数据进行写入操作,最后将复制数据替换原有数据,从而保证写操作不影响读操作。

    // 添加集合中不存在的元素
    int addAllAbsent(Collection<? extends E> c)
    // 该元素若不存在则添加
    boolean addIfAbsent(E e)

    JUC包中Set接口的实现类:CopyOnWriteArraySet、ConcurrentSkipListSet

      CopyOnWriteArraySet是线程安全的Set,它内部包含了一个CopyOnWriteArrayList,因此本质上是由CopyOnWriteArrayList实现的

      ConcurrentSkipListSet相当于线程安全的TreeSet。它是有序的Set。它由ConcurrentSkipListMap实现。

    Map

    ConcurrentHashMap:线程安全的HashMap。采用分段锁实现高效并发

    ConcurrentSkipListMap:线程安全的有序Map。使用跳表实现高效并发

    Queue

    ConcurrentLinkedQueue:线程安全的无界队列。底层采用单链表。支持FIFO  

           ConcurrentLinkedQueue使用链表作为数据结构,它采用无锁操作,可以任务是高并发环境下性能最好的队列。

           ConcurrentLinkedQueue是非阻塞线程安全队列,无界,故不太适合做生产者消费者模式,而LinkedBlockingQueue是阻塞线程安全队列,可以做到有界,通常用于生产者消费者模式。

    ConcurrentLinkedDeque:线程安全的无界双端队列。底层采用双向链表。支持FIFO和FILO

    ArrayBlockingQueue:数组实现的阻塞队列

    // 在队尾添加指定元素,若队已满则等待指定时间
    boolean offer(E e, long timeout, TimeUnit unit)
    // 获取并删除队首元素,若队为空则阻塞等待
    E take()
    // 添加指定元素,若队已满则一直等待
    void put(E e)
    // 获取队首元素,若队为空,则等待指定时间
    E poll(long timeout, TimeUnit unit)

    LinkedBlockingQueue:链表实现的阻塞队列

    LinkedBlockingDeque:双向链表实现的双端阻塞队列

  • 相关阅读:
    初始ASP.NET数据控件【续 DataList】
    初始ASP.NET数据控件GridView
    初始ADO.NET数据操作
    初识 Asp.Net数据验证控件
    【Socket编程】Java通信是这样炼成的
    JAVA之I/O 输入输出流详解
    浅入深出之Java集合框架(下)
    浅入深出之Java集合框架(中)
    浅入深出之Java集合框架(上)
    全面解释java中StringBuilder、StringBuffer、String类之间的关系
  • 原文地址:https://www.cnblogs.com/coder-lzh/p/9582910.html
Copyright © 2011-2022 走看看