我正在编写一个使用ConcurrentHashMap存储数据的类。
多个线程可以从ConcurrentHashMap中保存/删除数据。我还需要公开一个接口,该接口允许遍历ConcurrentHashMap,而其他线程不断修改它。遍历操作不经常使用,不需要代表ConcurrentHashMap的100%准确状态,但是它不应崩溃或返回垃圾。
我想我可以对映射键进行快照复制,并使用它来逐个检索值。如下所述:
class MyClass {
private final Map<String, DataBean> dataMap = new ConcurrentHashMap<>();
public String save(DataBean dataBean) {
String id = UUID.randomUUID().toString();
dataMap.put(id, dataBean);
return id;
}
public void remove(String id) {
dataMap.remove(id);
}
public Set<String> getKeySnapshot() {
// The problem is here. I am not sure if this is a thread-safe
// way to take a snapshot of the keySet of the map.
return new HashSet<>(dataMap.keySet());
}
public Optional<DataBean> getDataBean(String id) {
return Optional.ofNullable(dataMap.getOrDefault(id, null));
}
}
客户代码是这样;
class MyClient {
MyClass myClass = new MyClass();
public void myMethod() {
Set<String> keySnapShot = myClass.getKeySnapshot();
List<DataBean> dataBeanList = keySnapshot.stream.map(myClass::getDataBean).filter(Optional::isPresent).map(Optional::get).collect(Collectors.toList());
}
}
我不能完全确定getKeySnapshot方法中的注释行是否是线程安全的:
return new HashSet<>(dataMap.keySet());
它将成功创建地图键的快照副本吗?可以丢失键或包含条目的键,该条目不久后将被删除。只要它不崩溃或不返回垃圾就可以接受。
有人可以分享您的意见吗?