ConcurrentHashMap 用法和总结

本次提到的应用场景是这样的,对于任务启动来说(spring quartz任务),当有一个线程正在使用时,同样的任务不要再启动一次,这样可能导致数据出错。

使用ConcurrentHashMap 来保存任务的线程信息,如果当前任务线程已经在运行中,则退出。

主要代码如下:

 

private static ConcurrentHashMap threadMap = new ConcurrentHashMap();

for(final ThreadProfile profile:profiles){
			taskExecutor.execute(new Runnable(){
				public void run(){		
				    // 判断任务是否在执行,上一次任务还没有执行完,则本次退出
					if("y".equals(threadMap.get(profile.getCode()))){
						return;
					}
					threadMap.put(profile.getCode(), "y");
  }
}

 

 

 ConcurrentHashMap  可以提供较好的并发解决方案,它的思想比hashTable 和synchronizedMap更高明一些,

使用了几个技巧来获得高程度的并发以及避免锁定,包括为不同的 hash bucket(桶)使用多个写锁和使用 JMM 的不确定性来最小化锁被保持的时间——或者根本避免获取锁。

 ConcurrentHashMap 摒弃了单一的 map 范围的锁,取而代之的是由 32 个锁组成的集合,其中每个锁负责保护 hash bucket 的一个子集。锁主要由变化性操作(put() 和 remove())使用。具有 32 个独立的锁意味着最多可以有 32 个线程可以同时修改 map。这并不一定是说在并发地对 map 进行写操作的线程数少于 32 时,另外的写操作不会被阻塞——32 对于写线程来说是理论上的并发限制数目,但是实际上可能达不到这个值。但是,32 依然比 1 要好得多,而且对于运行于目前这一代的计算机系统上的大多数应用程序来说已经足够了。

 大多并发类使用同步来保证独占式访问一个数据结构(以及保持数据结构的一致性)。ConcurrentHashMap 没有采用独占性和一致性,它使用的链表是经过精心设计的,所以其实现可以检测 到它的列表是否一致或者已经过时。如果它检测到它的列表出现不一致或者过时,或者干脆就找不到它要找的条目,它就会对适当的bucket 锁进行同步并再次搜索整个链。这样做在一般的情况下可以优化查找,所谓的一般情况是指大多数检索操作是成功的并且检索的次数多于插入和删除的次数。
 我们看一下 get 方法实现

 

 V get(Object key, int hash) {
            if (count != 0) { // read-volatile
                HashEntry<K,V> e = getFirst(hash);
                while (e != null) {
                    if (e.hash == hash && key.equals(e.key)) {
                        V v = e.value;
                        if (v != null)
                            return v;
                        return readValueUnderLock(e); // recheck
                    }
                    e = e.next;
                }
            }
            

 

 检索操作首先为目标 bucket 查找头指针(是在不锁定的情况下完成的,所以说可能是过时的),然后在不获取 bucket 锁的情况下遍历 bucket 链。如果它不能发现要查找的值,就会同步并试图再次查找条目。

 ConcurrentHashMap 对于很多并发应用程序来说是一个非常有用的类,而且对于理解 JMM 何以取得较高性能的微妙细节是一个很好的例子。ConcurrentHashMap 是编码的经典,需要深刻理解并发和 JMM 才能够写得出。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值