五种并发包总结ConcurrentHashMap CopyOnWriteArrayList ArrayblockingQueue
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的更多相关文章
- java线程池与五种常用线程池策略使用与解析
背景:面试中会要求对5中线程池作分析.所以要熟知线程池的运行细节,如CachedThreadPool会引发oom吗? java线程池与五种常用线程池策略使用与解析 可选择的阻塞队列BlockingQu ...
- 数组复制的五种方式(遍历循环一一赋值、System.arraycopy、地址赋值、克隆clone()、Arrays.copyof())
package com.Summer_0424.cn; import java.util.Arrays; import java.util.concurrent.CopyOnWriteArrayLis ...
- Java并发包concurrent——ConcurrentHashMap
转: Java并发包concurrent——ConcurrentHashMap 2018年07月19日 20:43:23 Bill_Xiang_ 阅读数 16390更多 所属专栏: Java Conc ...
- java线程池和五种常用线程池的策略使用与解析
java线程池和五种常用线程池策略使用与解析 一.线程池 关于为什么要使用线程池久不赘述了,首先看一下java中作为线程池Executor底层实现类的ThredPoolExecutor的构造函数 pu ...
- JAVA中创建线程池的五种方法及比较
之前写过JAVA中创建线程的三种方法及比较.这次来说说线程池. JAVA中创建线程池主要有两类方法,一类是通过Executors工厂类提供的方法,该类提供了4种不同的线程池可供使用.另一类是通过Thr ...
- JavaScript常见的五种数组去重的方式
▓▓▓▓▓▓ 大致介绍 JavaScript的数组去重问题在许多面试中都会遇到,现在做个总结 先来建立一个数组 var arr = [1,2,3,3,2,'我','我',34,'我的',NaN,NaN ...
- Android之数据存储的五种方法
1.Android数据存储的五种方法 (1)SharedPreferences数据存储 详情介绍:http://www.cnblogs.com/zhangmiao14/p/6201900.html 优 ...
- 简述linux同步与异步、阻塞与非阻塞概念以及五种IO模型
1.概念剖析 相信很多从事linux后台开发工作的都接触过同步&异步.阻塞&非阻塞这样的概念,也相信都曾经产生过误解,比如认为同步就是阻塞.异步就是非阻塞,下面我们先剖析下这几个概念分 ...
- xmlHttp.readyState的五种状态
自己简单的总结一下 深入的了解可以看其他道友的 O(∩_∩)O readyState有五种可能的值: 0 (未初始化): (XMLHttpRequest)对象已经创建,但还没有调用open()方法. ...
随机推荐
- 什么是Gradle
一.什么是Gradle 简单的说,Gradle是一个构建工具,它是用来帮助我们构建app的,构建包括编译.打包等过程.我们可以为Gradle指定构建规则,然后它就会根据我们的“命令”自动为我们构建ap ...
- ios手机处理keyup事件时的兼容性问题
在安卓手机中没有任何问题,但在ios手机中出现当输入法中输入内容时,事件keyup没有效果 解决办法: //keyup的兼容性处理 var bind_name = 'input'; if (navig ...
- 有关JOIN ON的心得体会
在第一家公司工作大概有一年之后,我的上司开始让我负责一个项目了. 说起这个项目,其实就是类似一个报表系统的抽数据的活.我的主要工作就是将我们公司产生的数据进行抽取清理,然后生成一些带有分析性质的数据. ...
- Netty源码分析第8章(高性能工具类FastThreadLocal和Recycler)---->第7节: 获取异线程释放的对象
Netty源码分析第八章: 高性能工具类FastThreadLocal和Recycler 第七节: 获取异线程释放的对象 上一小节分析了异线程回收对象, 原理是通过与stack关联的WeakOrder ...
- pssh命令详解
基础命令学习目录首页 原文链接:https://www.cnblogs.com/kevingrace/p/6378719.html pssh提供OpenSSH和相关工具的并行版本.包括pssh,psc ...
- python爬虫项目(新手教程)之知乎(requests方式)
-前言 之前一直用scrapy与urllib姿势爬取数据,最近使用requests感觉还不错,这次希望通过对知乎数据的爬取为 各位爬虫爱好者和初学者更好的了解爬虫制作的准备过程以及requests请求 ...
- [linux] tmux终端复用神器 [转载]
转载https://www.cnblogs.com/kevingrace/p/6496899.html Tmux是一个优秀的终端复用软件,类似GNU Screen,但来自于OpenBSD,采用BSD授 ...
- servlet 和 threadlocal 与 web容器(理解threadlocal)
同步机制采用了“以时间换空间”的方式,提供一份变量,让不同的线程排队访问.而ThreadLocal采用了“以空间换时间”的方式,为每一个线程都提供了一份变量的副本,从而实现同时访问而互不影响. htt ...
- BugPhobia回顾篇章:团队Alpha阶段工作分析
0x00:序言 1 universe, 9 planets, 204 countries,809 islands, 7 seas, and i had the privilege to meet yo ...
- Task 7 买书最低价格问题
任务: 书店针对<哈利波特>系列书籍进行促销活动,一共5卷,用编号0.1.2.3.4表示,单独一卷售价8元, 具体折扣如下所示: 本数 折扣 2 5% 3 ...