文档章节

并发容器原理简介(一)

loda0128
 loda0128
发布于 2015/04/09 23:28
字数 1662
阅读 124
收藏 3
ConcurrentHashMap:采用分段锁机制,来锁住并发集合,目前是16段锁,最多可以允许16个线程同时并发访问对象

CopyOnWriteArrayList:采用读不加锁而写加锁的方式,虽然写的时候影响了效率,但是并发读的时候效率非常高,不过可能产生脏数据,如果不影响的话,可以选择使用。

CopyOnWriteArraySet:同上

ArrayBlockingQueue:使用offer添加时,如果设置了超时时间,那么填满数组就等待指定的超时时间,如果没有设置超时时间,那么立马返回,不等待。使用put添加时,如果填满了会一直等待。
使用poll取出时,如果没有设置超时时间,那么如果数组为空,就直接返回空,否则取出元素。如果设置了超时时间,那么如果数组不为空,取出元素,如果已经为空,那么根据指定时间等待(若没有指定时间,直接返回)。

LinkedBlockingQueue:与上类似,不过采用链表实现,并且本身由于链表的特点,实际操作的应该是读取链表头的元素而从链表末尾加入数据,也就是读写操作不会冲突,所以可以考虑将put、offer与take、poll分隔开,采用不同的锁。所以高并发下使用LinkedBlockingQueue是比ArrayBlockingQueue更优的选择。

AtomicInteger:当要进行并发计数的时候,使用该对象会比同步拥有更好的性能。他的方法incrementAndGet中将操作获取当前值current,获取到+1之后的值next,并对两个值进行CAS比较(利用操作系统比较内存值和current值,如果相同表示正常,返回true,incrementAndGet直接返回next值;如果不同表示获取值出现异常,返回false,循环重复以上所有操作直到拿到正确的值)。

重点来啦!!!

ThreadPoolExecutor:
corePoolSize:线程池的基本大小,也就是没有任务执行的时候线程池的大小。当线程池中线程数量小于基本大小时,每次来一个任务,开一个线程执行。当线程数量超过核心池大小的时候,会吧多的任务放到缓存队列中,队列满了的话才继续创建线程。

maximumPoolSize:线程池中同时存在的线程最大数量。

newFixedThreadPool设置了固定的corePoolSize和maximumPoolSize(两者值相等,均为传递的参数)。并且该线程池不存在超时时间,所以不会自动回收闲置的线程。虽然固定了线程的数量,但是如果有多余指定数量的任务提交过来的时候,就会将任务放到阻塞队列LinkedBlockingQueue中等待执行。该线程池也是web服务器常用的一种线程池。

newSingleThreadPool是一个线程池大小为1的 固定线程池 ,同时执行的任务数量只能为1个,多余的任务为扔到LinkedBlockingQueue等待执行。

newCachedThreadPool的corePoolSize为0,maximumPoolSize为最大整数(可以视为该线程池能够无限扩展),超时时间为1分钟,利用缓存队列SynchronousQueue(使用该队列是由于不这样做的话,直到工作队列满了才会增加线程,这通常不是我们想要的,所以利用该队列的话,一旦有任务加入进来,ThreadPoolExecutor检测到没有多余的线程的时候会马上先产生线程,来执行任务,而利用基本大小0作为回收线程的底线)。这样设置的目的是为了保证存在闲置线程并且空闲时间超过1分钟的时候,jvm能够最大化的回收这些线程,保证了性能的节约。但是他有个弊端就是,如果任务很多的时候,会产生很多线程,导致服务器超载。

备注:由于SynchronousQueue本质是将任务不断扔给一个新线程,所以这样在固定大小的线程池中就没有使用的意义了,因为,按照该队列的特性,长此以往,当任务数量超过线程池大小的时候,SynchronousQueue还欲求不满,需要新线程,而这样的需求又会因线程饱和而被拒绝,如此只会导致一系列的无意义动作。这也就是为什么将他用在一个可以无线扩充的线程池newCachedThreadPool的原因。

当任务之间存在依赖关系的时候,不适合使用固定大小的线程池,这样很容易因线程“饥渴”而导致死锁发生,为了避免该状况,一般会采用newCachedThreadPool。

newScheduledTheadPool:在该线程池出现之前,一般使用java.util.Timer进行延迟多少秒执行任务或者定时执行任务。
newScheduledTheadPool和Timer的比较:
前者可以使用多线程执行;后者只能单独一个线程执行定时或延时功能。
前者可以执行Callable任务,获取到任务返回值;后者由于采用的newThread直接启动的方式所以无法获取任务返回值。
前者一个线程抛出异常不影响其他线程任务;后者由于单线程,一个任务处异常,其他任务都执行不了。

而上述几个由doug lea提供好的几个线程池有一个共同的问题(当然newCachedThreadPool除外),就是当任务数量超过maximumPoolSize的时候,并且阻塞队列里面放满元素的时候,多余的任务怎么处理?
答案不言而喻,jdk肯定提供了一种机制来处理这些问题,这就是所谓的 饱和策略 。这些饱和策略为:
AbortPolicy(中止):默认饱和策略,一旦超过最大线程池数量,并且阻塞队列也放不下了,就会抛出线程。
DiscardPolicy(抛弃):会悄悄抛弃该任务
DiscardOldestPolicy(抛弃最旧):会抛弃下一个将被执行的任务,如果是优先队列,则会抛弃优先级最高的任务(加入队列的时间最长并且还没有被执行),所以该策略不要和优先队列一起使用
CallerRunsPolicy(调用者运行):将多余的任务回退给调用者,谁execute了该任务,就返回给该执行器。

参考文献:分布式java应用 基础与实践
                 java并发编程实战
                 java核心技术(一)

© 著作权归作者所有

共有 人打赏支持
上一篇: activemq/jms原理
下一篇: 位运算
loda0128
粉丝 93
博文 95
码字总数 119278
作品 0
朝阳
程序员
私信 提问
一年走向【Java架构师】之葵花宝典

大多数时候,不是我们不努力,而是不知从何下手,我深知一份好的学习资料是多么的重要,我们通常会把大量的时间都浪费在找资源上,本人搜集学习java架构师的经典学习路线如下可供参考!!! 一...

我一路狂奔
2017/05/20
395
1
java并发编程——并发容器类介绍

并发容器的简单介绍 JDK5中添加了新的concurrent包,相对同步容器而言,并发容器通过一些机制改进了并发性能。因为同步容器将所有对容器状态的访问都串行化了,这样保证了线程的安全性,所以...

长头发-dawn
2018/10/08
0
0
后台开发常问面试题集锦(问题搬运工,附链接)

Java基础问题 String的’+’的性能及原理 java之yield(),sleep(),wait()区别详解-备忘笔记 深入理解Java Stream流水线 抽象 & abstract关键字 Java final 修饰符知识点总结(必看篇) Java中的...

大黄有故事
2017/11/18
0
0
Java系列文章(全)

JVM JVM系列:类装载器的体系结构 JVM系列:Class文件检验器 JVM系列:安全管理器 JVM系列:策略文件 Java垃圾回收机制 深入剖析Classloader(一)--类的主动使用与被动使用 深入剖析Classloader(二...

www19
2017/07/04
0
0
下一代工具集 BuildKit 大揭秘,Docker 专家带你了解背后的点点滴滴

本文首发自“Docker公司”公众号(ID:docker-cn) 编译丨小东 每周一、三、五 与您不见不散! 上周,我们在 Docker 总部成功地举办了 Docker San Francisco 的分会活动。本次活动主要聚焦在...

docker公司
2018/08/06
0
0

没有更多内容

加载失败,请刷新页面

加载更多

深入理解Spring MVC 思想

目录 一、前言 二、spring mvc 核心类与接口 三、spring mvc 核心流程图 四、spring mvc DispatcherServlet说明 五、spring mvc 父子上下文的说明 六、springMVC-mvc.xml 配置文件片段讲解 ...

呵呵哒灬
今天
3
0
数据库技术-Mysql主从复制与数据备份

数据库技术-Mysql 主从复制的原理: MySQL中数据复制的基础是二进制日志文件(binary log file)。一台MySQL数据库一旦启用二进制日志后,其作为master,它的数据库中所有操作都会以“事件”...

须臾之余
昨天
12
0
Git远程仓库——GitHub的使用(一)

Git远程仓库——GitHub的使用(一) 一 、 Git远程仓库 由于你的本地仓库和GitHub仓库之间的传输是通过SSH加密的,所以需要一下设置: 步骤一、 创建SSH key 在用户主目录下,看看有没有.ss...

lwenhao
昨天
4
0
SpringBoot 整合

springBoot 整合模板引擎 SpringBoot 整合Mybatis SpringBoot 整合redis SpringBoot 整合定时任务 SpringBoot 整合拦截器...

细节探索者
昨天
1
0
第二个JAVA应用

第二个JAVA应用 方法一:配置文件: # cd /usr/local/tomcat/conf/# vim server.xml</Host> <Host name="www.wangzb.cc" appBase="/data/wwwroot/www.wangzb.cc" //引用所......

wzb88
昨天
2
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部