在并发量很小的情况下,也许大家平时用到的HashMap比较多。我们知道HashMap是线程不安全的,在多线程使用HashMap进行put操作会引起死循环,导致cpu利用率接近100%(已测试模拟100000个线程执行以uuid为key,put值操作,cpu达到百分之90多)。HashTable是使用synchronized保证线程安全的,但是线程竞争激烈的情况下效率低,如线程 1 使用 put 进行添加元素,线程 2 不但不能使用 put 方法添加元素,并且也不能使用 get 方法来获取元素。
ConcurrentHashMap解决高并发情况下线程安全和效率问题,是由Segment数组结构和HashEntry数组结构组成。Segment是一种可重入锁ReentrantLock,在ConcurrentHashMap里扮演锁的角色,HashEntry则用于存储键值对数据。一个ConcurrentHashMap里包含一个Segment数组,Segment的结构和HashMap类似,是一种数组和链表结构,一个Segment里包含一个HashEntry数组,每个HashEntry是一个链表结构的元素,每个Segment守护一个HashEntry数组里的元素,当对HashEntry数组的数据进行修改时,必须首先获得它对应的Segment锁。所图所示:[img]
[/img]
ConcurrentHashMap的get操作实现非常简单和高效。先经过一次再哈希,然后使用这个哈希值通过哈希运算定位到segment,再通过哈希算法定位到元素。get 操作的高效之处在于整个 get 过程不需要加锁,除非读到的值是空的才会加锁重读。put操作需要对共享变量进行写入操作,所以为了线程安全,在操作共享变量时必须得加锁。Put 方法首先定位到 Segment,然后在 Segment 里进行插入操作。插入操作需要经历两个步骤:第一步判断是否需要对 Segment 里的 HashEntry 数组进行扩容,第二步定位添加元素的位置然 后放在 HashEntry 数组里。size操作统计元素的大小,也就是统计所有Segment里元素的求和。统计的时候不是把所有Segment的put,remove,clean方法锁住,而是先尝试 2 次通过不锁住 Segment 的方式来统计各个Segment 大小,如 果统计的过程中,容器的 count 发生了变化,则再采用加锁的方式来统计所有 Segment 的大小。那么判断count是否发生变化判断的条件是:使用 modCount 变 量,在 put , remove 和 clean 方法里操作元素前都会将变量 modCount 进行加 1,那么在统计 size 前 后比较 modCount 是否发生变化,从而得知容器的大小是否发生变化。
ConcurrentLinkedQueue 是一个基于链接节点的无界线程安全队列,它采用先进先出的规则对 节点进行排序,当我们添加一个元素的时候,它会添加到队列的尾部,当我们获取一个元素时,它 会返回队列头部的元素。类图结构如下:
由图可知:它由 head 节点和 tair 节点组成,每个节点(Node)由节点元素(item)
和指向下一个节点的引用(next)组成,节点与节点之间就是通过这个 next 关联起来,从而组成一张 链表结构的队列。默认情况下 head 节点存储的元素为空,tair 节点等于 head 节点。
这两个类是java.util.concurrent包下的类,以后工作中遇到要求多线程安全情况下可以尝试用这两个类。
参考资料:方腾飞java并发
- 大小: 298.3 KB
- 大小: 215.7 KB
分享到:
相关推荐
backport-util-concurrent.jarbackport-util-concurrent.jarbackport-util-concurrent.jar
1. java.util.concurrent - Java 并发工具包 2. 阻塞队列 BlockingQueue 3. 数组阻塞队列 ArrayBlockingQueue 4. 延迟队列 DelayQueue 5. 链阻塞队列 LinkedBlockingQueue 6. 具有优先级的阻塞队列 ...
java并发工具包 java.util.concurrent中文版-带书签版
java.util.concurrent - Java 并发工具包 2. 阻塞队列 BlockingQueue 3. 数组阻塞队列 ArrayBlockingQueue 4. 延迟队列 DelayQueue 5. 链阻塞队列 LinkedBlockingQueue 6. 具有优先级的阻塞队列 ...
标签:atlassian-util-concurrent-0.0.12.jar.zip,atlassian,util,concurrent,0.0.12,jar.zip包下载,依赖包
backport-util-concurrent-3.1.jar 和 geronimo-stax-api_1.0_spec-1.0.1.jar 复制到 MyEclipse 6.5\eclipse\plugins\Axis2_Codegen_Wizard_1.3.0\lib 文件夹下。 (3).注册此 jar 包: 修改MyEclipse 6.5\eclipse...
java并发工具包 java.util.concurrent中文版pdf
asm-util-3.2.jarasm-util-3.2.jarasm-util-3.2.jarasm-util-3.2.jarasm-util-3.2.jarasm-util-3.2.jarasm-util-3.2.jarasm-util-3.2.jarasm-util-3.2.jarasm-util-3.2.jarasm-util-3.2.jarasm-util-3.2.jarasm-util...
- copy %AXIS2_HOME%\lib\backport-util-concurrent-3.1.jar 到%ECLIPSE_HOME%\plugins\Axis2_Codegen_Wizard_1.3.0\lib - 注册此 jar 包: 編輯 %ECLIPSE_HOME%\plugins\Axis2_Codegen_Wizard_1.3.0\plugin.xml , ...
java-util-iterator.pdfjava-util-iterator.pdfjava-util-iterator.pdf
赠送jar包:jetty-util-9.4.43.v20210629.jar; 赠送原API文档:jetty-util-9.4.43.v20210629-javadoc.jar; 赠送源代码:jetty-util-9.4.43.v20210629-sources.jar; 赠送Maven依赖信息文件:jetty-util-9.4.43.v...
包含hadoop平台Java开发的所有所需jar包,例如activation-1.1.jar apacheds-i18n-2.0.0-M15.jar apacheds-kerberos-codec-2.0.0-M15.jar api-asn1-api-1.0.0-M20.jar api-util-1.0.0-M20.jar asm-3.2.jar avro-1.7.7...
在Eclipse3.5用Axis2中创建wsdl文件时,在最后一步出现如下错误: An error ocCurred while ...解决用到的jar包,两个jar包在backport-util-concurrent-3.1.jar和geronimo-stax-api_1.0_spec-1.0.1.jar.zip的压缩文件中
赠送jar包:jetty-util-9.4.11.v20180605.jar; 赠送原API文档:jetty-util-9.4.11.v20180605-javadoc.jar; 赠送源代码:jetty-util-9.4.11.v20180605-sources.jar; 赠送Maven依赖信息文件:jetty-util-9.4.11.v...
赠送jar包:jetty-util-ajax-9.3.19.v20170502.jar; 赠送原API文档:jetty-util-ajax-9.3.19.v20170502-javadoc.jar; 赠送源代码:jetty-util-ajax-9.3.19.v20170502-sources.jar; 赠送Maven依赖信息文件:jetty-...
java-util-1.3.1.jar.zip
1. java.util.concurrent - Java 并发工具包 2. 阻塞队列 BlockingQueue 3. 数组阻塞队列 ArrayBlockingQueue 4. 延迟队列 DelayQueue 5. 链阻塞队列 LinkedBlockingQueue 6. 具有优先级的阻塞队列 ...
Tomcat内存溢出的解决方法(java.util.concurrent.ExecutionException:java.lang.OutOfMemoryError),内附解决方案!