Findbugs:NP_LOAD_OF_KNOWN_NULL_VALUE - 单例 class 双重检查
Findbugs: NP_LOAD_OF_KNOWN_NULL_VALUE - Singleton class Double checking
我有一个 Singleton class,在构造函数中进行了双重检查。
Findbugs 报告以下错误。
Load of known null value in ... NP_LOAD_OF_KNOWN_NULL_VALUE
class SomeClass {
private Object lock = new Object();
private Map<String,Resource> resourceMap = new HashMap<>();
public Resource getResource(String resourceId) {
if (resourceMap.get(resourceId) == null) {
synchronized(lock) {
if (resourceMap.get(resourceId) == null)
Resource resource = new Resource();
resourceMap.put(resourceId,resource);
}
}
return resourceMap.get(resourceId);
}
}
我可以使用静态对象引用,但要求是为唯一请求 ID 创建单个对象。
比如说,请求 ID 1 将用于多个请求。因此,我们必须为此在 运行 时间为所有请求 ID 创建一个对象。
谢谢,
您应该使用 ConcurrentMap 而不是双重检查锁定模式。关于地图元素的可见性,您的方法不正确(有关可见性的更多详细信息,请参阅以下 question)。
class SomeClass {
private final ConcurrentMap<String, Resource> resourceMap = new ConcurrentHashMap<>();
public Resource getResource(String resourceId) {
return resourceMap.computeIfAbsent(resourceId, r -> new Resource());
}
private static class Resource {}
}
编辑以使用 LRU 替换策略限制为 10 个元素
您可以使用 Guava cache that uses LRU strategy for default size-based eviction.
import com.google.common.cache.*;
class SomeClass {
private final LoadingCache<String, Resource> resourceMap =
CacheBuilder.newBuilder()
.maximumSize(10L)
.build(new CacheLoader<String, Resource>() {
@Override
public Resource load(String key) {
return new Resource();
}
});
public Resource getResource(String resourceId) {
return resourceMap.getUnchecked(resourceId);
}
private static class Resource {
}
}
我有一个 Singleton class,在构造函数中进行了双重检查。
Findbugs 报告以下错误。
Load of known null value in ... NP_LOAD_OF_KNOWN_NULL_VALUE
class SomeClass {
private Object lock = new Object();
private Map<String,Resource> resourceMap = new HashMap<>();
public Resource getResource(String resourceId) {
if (resourceMap.get(resourceId) == null) {
synchronized(lock) {
if (resourceMap.get(resourceId) == null)
Resource resource = new Resource();
resourceMap.put(resourceId,resource);
}
}
return resourceMap.get(resourceId);
}
}
我可以使用静态对象引用,但要求是为唯一请求 ID 创建单个对象。
比如说,请求 ID 1 将用于多个请求。因此,我们必须为此在 运行 时间为所有请求 ID 创建一个对象。
谢谢,
您应该使用 ConcurrentMap 而不是双重检查锁定模式。关于地图元素的可见性,您的方法不正确(有关可见性的更多详细信息,请参阅以下 question)。
class SomeClass {
private final ConcurrentMap<String, Resource> resourceMap = new ConcurrentHashMap<>();
public Resource getResource(String resourceId) {
return resourceMap.computeIfAbsent(resourceId, r -> new Resource());
}
private static class Resource {}
}
编辑以使用 LRU 替换策略限制为 10 个元素
您可以使用 Guava cache that uses LRU strategy for default size-based eviction.
import com.google.common.cache.*;
class SomeClass {
private final LoadingCache<String, Resource> resourceMap =
CacheBuilder.newBuilder()
.maximumSize(10L)
.build(new CacheLoader<String, Resource>() {
@Override
public Resource load(String key) {
return new Resource();
}
});
public Resource getResource(String resourceId) {
return resourceMap.getUnchecked(resourceId);
}
private static class Resource {
}
}