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 {
    }
}