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);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值