ConcurrentHashMap中的值抛出NullPointerException

时间:2019-05-22 06:44:29

标签: java concurrency nullpointerexception

我正在维护使用ConcurrentHashMap的多线程旧代码。

其他方法中有添加和删除操作。

在以下代码中,在从映射中收集了几个值之后的某个时刻,它在执行NullPointerException时抛出synchronize(value)

public class MyClass{

    private final Map<MyObj, Map<String, List<String>>> conMap = new ConcurrentHashMap<>();

    //...

    public void doSomthing((MyObj id){
        List<Map<String, List<String>>> mapsList = new LinkedList<>();
        for(MyObj objId: conMap.keySet()){              
            if(objId.key1.equals(id.key1)){
                mapsList.add(conMap.get(objId));
            }
        }

        for(Map<String, List<String>> map: mapsList){
            synchronized(map){                   // <-- NullPointerException here
                //...
            }
    }

    //...

}

我觉得也许在第一个循环的迭代过程中,记录正在被删除。而当行:

mapsList.add(conMap.get(objId));

正在执行,objId不再存在,mapsList添加空值,因此在第二个循环NullPoinerException中被抛出。

还有其他原因导致此异常吗?

1 个答案:

答案 0 :(得分:1)

您迷上了Check-Then-Act反模式。它意味着检查条件(如键的存在),然后对其进行操作(如调用get),而忽略条件在其间可能发生变化的可能性。

因此,在遍历conMap.keySet()时会遇到一个特定的键,但是当您调用conMap.get(objId)时,该键可能不再在映射中,这通过返回{{1 }}。

强烈建议使用具有合适的null / hashCode实现的键类型,因此您无需遍历整个地图来查找匹配项,而可以使用单个{{1 }}。

但是,当您必须遍历地图并需要值时,请遍历条目集而不是键集。

equals