gpt4 book ai didi

java - ConcurrentHashMap 中的值抛出 NullPointerException

转载 作者:行者123 更新时间:2023-12-02 09:52:07 25 4
gpt4 key购买 nike

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

其他方法中还有add、remove的操作。

在下面的代码中,在从 map 收集一些值后的某个时刻,它会抛出 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添加 null 并因此在第二个循环期间 NullPoinerException被抛出。

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

最佳答案

您已经陷入了“检查然后行动”的反模式。它意味着检查一个条件(例如 key 是否存在),然后对其进行操作(例如调用 get),忽略条件在其间发生变化的可能性。

因此,在迭代 conMap.keySet() 时,您会遇到特定的键,但是当您调用 conMap.get(objId) 时,该键可能会不再在 map 中,这是通过返回 null 来报告的。

强烈建议使用具有合适的 hashCode/equals 实现的键类型,这样您就不需要迭代整个映射来查找匹配项,但可以使用单个 get(id)

但是,当您必须迭代 map 并需要值时,请迭代条目集而不是键集。

public void doSomething(MyObj id){
// see https://stackoverflow.com/q/322715/2711488
List<Map<String, List<String>>> mapsList = new ArrayList<>();

for(Map.Entry<MyObj, Map<String, List<String>>> e: conMap.entrySet()){
if(e.getKey().key1.equals(id.key1)){
mapsList.add(e.getValue());
}
}

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

关于java - ConcurrentHashMap 中的值抛出 NullPointerException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56250791/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com