首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > 编程 >

ConcurrentHashMap与synchronizedHashMap的抉择

2012-12-26 
ConcurrentHashMap与synchronizedHashMap的选择public class MyClass{private MapString,ListTimerConfi

ConcurrentHashMap与synchronizedHashMap的选择
public class MyClass{
  private Map<String,List<TimerConfigLoader>> listenerMap = Collections.synchronizedMap(new HashMap<String,List<TimerConfigLoader>>());
 
    ..........
    public void registClient(String name,TimerConfigLoader configLoader){
        if(listenerMap.containsKey(name)){
            List<TimerConfigLoader> ts = listenerMap.get(name);
            ts.add(configLoader);
        }else{
            List<TimerConfigLoader> ts = new ArrayList<TimerConfigLoader>();
            ts.add(configLoader);
            listenerMap.put(name, ts);
        }
    }
        
    public void unregistClient(String name,TimerConfigLoader configLoader){
        if(listenerMap.containsKey(name)){
            List<TimerConfigLoader> ts = listenerMap.get(name);
            ts.remove(configLoader);
        }
    }
}

这段代码可能存在的问题 有:
a、空指针
listenerMap是可以存放空值的,
  if(listenerMap.containsKey(name)){  
            List<TimerConfigLoader> ts = listenerMap.get(name);  
这里ts仍然可能是null

b、安全问题
containsKey、get、put、remove在一起使用的时候,不是原子操作。如果在并发使用时,是存在着安全的问题。

修改方案有两种:(1)在这些操作外加 锁 (2)使用ConcurrentHashMap,其中提供了putIfAbsent原子操作的方法

疑问:(1)这两种修改方案 哪一种更好?什么时候使用ConcurrentHashMap,什么时候使用Collections.synchronizedXXX?
       个人的看法是使用ConcurrentHashMap,在java6,ConcurrentHashMap提供了原子操作的方法,提供了更好的性能和伸缩性。
      在ConcurrentHashMap不够用的时候,比如需要独占性访问,使用Collections.synchronizedXXX

(2)将上面代码修改成
public void registClient(String name,TimerBasedConfigLoader configLoader){
        List<TimerBasedConfigLoader> ts = listenerMap.get(name);
        if(ts == null){
            listenerMap.putIfAbsent(name, new ArrayList<TimerBasedConfigLoader>());
          //这里一定要再调用下get方法。在并发时,当前线程执行putIfAbsent可能失败,但一定会有一个线程执行成功,所以要调用get,获取一下。
            ts = listenerMap.get(name);
        }
        ts.add(configLoader);
    }

热点排行