1、常用的五种并发包

  • ConcurrentHashMap
  • CopyOnWriteArrayList
  • CopyOnWriteArraySet
  • ArrayBlockingQueue
  • LinkedBlockingQueue

2、ConcurrentHashMap

  • 线程安全的HashMap的实现
  • 数据结构:一个指定个数的Segment数组,数组中的每一个元素Segment相当于一个HashTable(一个HashEntry[])
  • 扩容的话,只需要扩自己的Segment而非整个table扩容
  • key与value均不可以为null,而hashMap可以
  • 向map添加元素
    • 根据key获取key.hashCode的hash值
    • 根据hash值算出将要插入的Segment
    • 根据hash值与Segment中的HashEntry的容量-1按位与获取将要插入的HashEntry的index
    • 若HashEntry[index]中的HashEntry链表有与插入元素相同的key和hash值,根据onlyIfAbsent决定是否替换旧值
    • 若没有相同的key和hash,直接返回将新节点插入链头,原来的头节点设为新节点的next(采用的方式与HashMap一致,都是HashEntry替换的方法)
  • ConcurrentHashMap基于concurrencyLevel划分出多个Segment来存储key-value,这样的话put的时候只锁住当前的Segment,可以避免put的时候锁住整个map,从而减少了并发时的阻塞现象
  • 从map中获取元素
    • 根据key获取key.hashCode的hash值
    • 根据hash值与找到相应的Segment
    • 根据hash值与Segment中的HashEntry的容量-1按位与获取HashEntry的index
    • 遍历整个HashEntry[index]链表,找出hash和key与给定参数相等的HashEntry,例如e
      • 如没找到e,返回null
      • 如找到e,获取e.value
        • 如果e.value!=null,直接返回
        • 如果e.value==null,则先加锁,等并发的put操作将value设置成功后,再返回value值
  • 对于get操作而言,基本没有锁,只有当找到了e且e.value等于null,有可能是当下的这个HashEntry刚刚被创建,value属性还没有设置成功,这时候我们读到是该HashEntry的value的默认值null,所以这里加锁,等待put结束后,返回value值
  • 加锁情况(分段锁):
    • put
    • get中找到了hash与key都与指定参数相同的HashEntry,但是value==null的情况
    • remove
    • size():三次尝试后,还未成功,遍历所有Segment,分别加锁(即建立全局锁)

3、CopyOnWriteArrayList

  • 线程安全且在读操作时无锁的ArrayList
  • 采用的模式就是"CopyOnWrite"(即写操作-->包括增加、删除,使用复制完成)
  • 底层数据结构是一个Object[],初始容量为0,之后每增加一个元素,容量+1,数组复制一遍
  • 遍历的只是全局数组的一个副本,即使全局数组发生了增删改变化,副本也不会变化,所以不会发生并发异常。但是,可能在遍历的过程中读到一些刚刚被删除的对象
  • 增删改上锁、读不上锁
  • 读多写少且脏数据影响不大的并发情况下,选择CopyOnWriteArrayList

4、CopyOnWriteArraySet

  • 基于CopyOnWriteArrayList,不添加重复元素

5、ArrayBlockingQueue

  • 基于数组、先进先出、线程安全,可实现指定时间的阻塞读写,并且容量可以限制
  • 组成:一个对象数组+1把锁ReentrantLock+2个条件Condition
  • 三种入队对比
    • offer(E e):如果队列没满,立即返回true; 如果队列满了,立即返回false-->不阻塞
    • put(E e):如果队列满了,一直阻塞,直到数组不满了或者线程被中断-->阻塞
    • offer(E e, long timeout, TimeUnit unit):在队尾插入一个元素,,如果数组已满,则进入等待,直到出现以下三种情况:-->阻塞
      • 被唤醒
      • 等待时间超时
      • 当前线程被中断
  • 三种出对对比
    • poll():如果没有元素,直接返回null;如果有元素,出队
    • take():如果队列空了,一直阻塞,直到数组不为空或者线程被中断-->阻塞
    • poll(long timeout, TimeUnit unit):如果数组不空,出队;如果数组已空且已经超时,返回null;如果数组已空且时间未超时,则进入等待,直到出现以下三种情况:
      • 被唤醒
      • 等待时间超时
      • 当前线程被中断
  • 需要注意的是,数组是一个必须指定长度的数组,在整个过程中,数组的长度不变,队头随着出入队操作一直循环后移
  • 锁的形式有公平与非公平两种
  • 在只有入队高并发或出队高并发的情况下,因为操作数组,且不需要扩容,性能很高

6、LinkedBlockingQueue

  • 基于链表实现,读写各用一把锁,在高并发读写操作都多的情况下,性能优于ArrayBlockingQueue
  • 组成一个链表+两把锁+两个条件
  • 默认容量为整数最大值,可以看做没有容量限制
  • 三种入队与三种出队与上边完全一样,只是由于LinkedBlockingQueue的的容量无限,在入队过程中,可能根本没有阻塞等待

五种并发包总结ConcurrentHashMap CopyOnWriteArrayList ArrayblockingQueue的更多相关文章

  1. java线程池与五种常用线程池策略使用与解析

    背景:面试中会要求对5中线程池作分析.所以要熟知线程池的运行细节,如CachedThreadPool会引发oom吗? java线程池与五种常用线程池策略使用与解析 可选择的阻塞队列BlockingQu ...

  2. 数组复制的五种方式(遍历循环一一赋值、System.arraycopy、地址赋值、克隆clone()、Arrays.copyof())

    package com.Summer_0424.cn; import java.util.Arrays; import java.util.concurrent.CopyOnWriteArrayLis ...

  3. Java并发包concurrent——ConcurrentHashMap

    转: Java并发包concurrent——ConcurrentHashMap 2018年07月19日 20:43:23 Bill_Xiang_ 阅读数 16390更多 所属专栏: Java Conc ...

  4. java线程池和五种常用线程池的策略使用与解析

    java线程池和五种常用线程池策略使用与解析 一.线程池 关于为什么要使用线程池久不赘述了,首先看一下java中作为线程池Executor底层实现类的ThredPoolExecutor的构造函数 pu ...

  5. JAVA中创建线程池的五种方法及比较

    之前写过JAVA中创建线程的三种方法及比较.这次来说说线程池. JAVA中创建线程池主要有两类方法,一类是通过Executors工厂类提供的方法,该类提供了4种不同的线程池可供使用.另一类是通过Thr ...

  6. JavaScript常见的五种数组去重的方式

    ▓▓▓▓▓▓ 大致介绍 JavaScript的数组去重问题在许多面试中都会遇到,现在做个总结 先来建立一个数组 var arr = [1,2,3,3,2,'我','我',34,'我的',NaN,NaN ...

  7. Android之数据存储的五种方法

    1.Android数据存储的五种方法 (1)SharedPreferences数据存储 详情介绍:http://www.cnblogs.com/zhangmiao14/p/6201900.html 优 ...

  8. 简述linux同步与异步、阻塞与非阻塞概念以及五种IO模型

    1.概念剖析 相信很多从事linux后台开发工作的都接触过同步&异步.阻塞&非阻塞这样的概念,也相信都曾经产生过误解,比如认为同步就是阻塞.异步就是非阻塞,下面我们先剖析下这几个概念分 ...

  9. xmlHttp.readyState的五种状态

    自己简单的总结一下 深入的了解可以看其他道友的 O(∩_∩)O readyState有五种可能的值: 0 (未初始化): (XMLHttpRequest)对象已经创建,但还没有调用open()方法. ...

随机推荐

  1. 自动化jenkins报:ModuleNotFoundError: No module named 'common'

    直接执行脚本是没有问题,报如下错误: 你已经在run.py脚本加路径了为什么还会报这个错呢,就是你加的路径,应该在所有的包上面,才不会报这个错,如下: 注:以下是我的解决方法仅作参考.如果我的发表的内 ...

  2. 记录Centos7搭建ftp服务器以及遇到的各种坑

    前言 今天被经理要求搭建ftp服务器,然后就去网上搜索了一下教程.搭建成功后(遇到的坑不少)特此记录一下.因为是为了记录一下整个操作流程以防以后使用所以比较啰嗦. 目录 1.安装vsftpd 2.创建 ...

  3. JDBC Mysql 驱动连接异常

    在做JDBC连接Mysql的时候遇到了三个异常: 第一个是:mysql8.0 caching_sha2_password 这个异常是由于是因为在mysql8.0之前的密码规则是mysql_native ...

  4. 6. 使用antd pro构建web页面

    前言 在开始之前,希望我们已经掌握了一部分react的知识,由于没有太多经验,其实我也是属于摸索阶段.这里假定我们已经了解了react,redux和dva/umi相关的知识.并有做过相关练习. 如果还 ...

  5. Java中 static、final和static final的特点及区别

    final: final可以修饰:属性,方法,类,局部变量(方法中的变量) final修饰的属性的初始化可以在编译期,也可以在运行时,初始化后不能被改变. final修饰的属性跟具体对象有关,在运行期 ...

  6. IIS6/IIS7环境下实现支持mp4视频随意拖动、预览播放、边下载边播放

    前几天,一客户需要在IIS环境下实现MP4视频可以随意拖动观看,边下载边播放.一看这要求,IIS本身是无法实现,想着应该需要用插件,于是GG一番,还真找到这样的插件,此组件为H264-Streamin ...

  7. PPIO去中心化存储的了解和记录

    目录 介绍 FileCoin P2P技术给去中心化云存储的好处 剩余资源的再次使用 市场竞争会激发民间的智慧 PPIO的2种冗余模式 全副本模式 纠删副本模式 为什么PPIO要设计支付代理节点? 一些 ...

  8. Windows下 搭建redis集群

    Windows下搭建redis集群教程 一,redis集群介绍 Redis cluster(redis集群)是在版本3.0后才支持的架构,和其他集群一样,都是为了解决单台服务器不够用的情况,也防止了主 ...

  9. Django_csrf

    CSRF攻击介绍 CSRF 攻击可以在受害者毫不知情的情况下以受害者名义伪造请求发送给受攻击站点,从而在并未授权的情况下执行在权限保护之下的操作.比如说,受害者 Bob 在银行有一笔存款,通过对银行的 ...

  10. 05慕课网《进击Node.js基础(一)》HTTP概念进阶(同步/异步)

    HTTP模块介绍 支持http协议的更多特性 不缓存请求和响应 API比较底层处理流相关,信息解析 HTTP相关概念 回调 将函数作为参数传到执行函数中,参数函数在执行函数中嵌套执行 function ...