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);
}
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);
}