遍历ConcurrentHashMap的线程安全方法

时间:2019-05-12 18:41:11

标签: java multithreading concurrenthashmap

我正在编写一个使用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());

它将成功创建地图键的快照副本吗?可以丢失键或包含条目的键,该条目不久后将被删除。只要它不崩溃或不返回垃圾就可以接受。

有人可以分享您的意见吗?

0 个答案:

没有答案