首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >ConcurrentHashMap的迭代一致性保证

ConcurrentHashMap的迭代一致性保证
EN

Stack Overflow用户
提问于 2014-10-05 11:43:59
回答 2查看 323关注 0票数 2

我正在编写一段代码,需要在ConcurrentHashMap上设置一个时间上一致的迭代器。

对于迭代器的一致性,docs有这样的说法:

保证在施工时正确地遍历元素,并且可以(但不能保证)反映施工后的任何修改。

但这有点粗略(“五月”)。对ConcurrentHashMap来说,除了这些之外,还有什么特别的保证吗?

如果没有,是否还有其他并发映射实现确实提供了更好的保证?(同一线程的时间点一致性)

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2014-10-06 16:27:39

您想要的保证+非常大的数据集将涉及一些事务机制或快照锁定:

代码语言:javascript
复制
Snapshot<K, V> viewport = map.lockSnapshot();
try {
    ... // work with version-fixed viewport.
} finally {
    map.unlockSnapshot(viewport);
}

也许你需要事务性的键值存储?看看GridGain解决方案,它们具有这样的功能(以及上面的很多功能)。

票数 2
EN

Stack Overflow用户

发布于 2014-10-06 15:49:11

您可以使用副本上的地图实现:

代码语言:javascript
复制
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.atomic.AtomicReference;

/**
 * A thread-safe version of {@link Map} in which all operations that change the
 * Map are implemented by making a new copy of the underlying Map.
 * <p/>
 * While the creation of a new Map can be expensive, this class is designed for
 * cases in which the primary function is to read data from the Map, not to
 * modify the Map.  Therefore the operations that do not cause a change to this
 * class happen quickly and concurrently.
 *
 * @author <a href="mailto:Kuzma.Deretuke@gmail.com">Kuzma Deretuke</a>
 */
public class CopyOnWriteHashMap<K, V> implements Map<K, V>, Cloneable {
    private AtomicReference<Map<K, V>> internalMap = new AtomicReference<Map<K, V>>();

    /**
     * Creates a new instance of CopyOnWriteHashMap.
     */
    public CopyOnWriteHashMap() {
        internalMap.set(new HashMap<K, V>());
    }

    /**
     * Creates a new instance of CopyOnWriteHashMap with the specified initial size.
     *
     * @param initialCapacity The initial size of the Map.
     */
    public CopyOnWriteHashMap(int initialCapacity) {
        internalMap.set(new HashMap<K, V>(initialCapacity));
    }

    /**
     * Creates a new instance of CopyOnWriteHashMap in which the initial data,
     * being held by this map, is contained in the supplied map.
     *
     * @param data A Map containing the initial contents to be placed into this class.
     */
    public CopyOnWriteHashMap(Map<K, V> data) {
        internalMap.set(new HashMap<K, V>(data));
    }

    @Override
    public V put(K key, V value) {
        Map<K, V> oldMap;
        Map<K, V> newMap;
        V val;
        do {
            oldMap = internalMap.get();
            newMap = new HashMap<K, V>(oldMap);
            val = newMap.put(key, value);
        }
        while (!internalMap.compareAndSet(oldMap, newMap));
        return val;
    }

    @Override
    public V remove(Object key) {
        Map<K, V> oldMap;
        Map<K, V> newMap;
        V val;
        do {
            oldMap = internalMap.get();
            newMap = new HashMap<K, V>(oldMap);
            val = newMap.remove(key);
        }
        while (!internalMap.compareAndSet(oldMap, newMap));
        return val;
    }

    @Override
    public void putAll(Map<? extends K, ? extends V> newData) {
        Map<K, V> oldMap;
        Map<K, V> newMap;
        do {
            oldMap = internalMap.get();
            newMap = new HashMap<K, V>(oldMap);
            newMap.putAll(newData);
        }
        while (!internalMap.compareAndSet(oldMap, newMap));
    }

    @Override
    public void clear() {
        internalMap.set(new HashMap<K, V>());
    }

    //
    //  Below are methods that do not modify the internal map
    //          

    @Override
    public int size() {
        return internalMap.get().size();
    }

    @Override
    public boolean isEmpty() {
        return internalMap.get().isEmpty();
    }

    @Override
    public boolean containsKey(Object key) {
        return internalMap.get().containsKey(key);
    }

    @Override
    public boolean containsValue(Object value) {
        return internalMap.get().containsValue(value);
    }

    @Override
    public V get(Object key) {
        return internalMap.get().get(key);
    }

    @Override
    public Set<K> keySet() {
        return internalMap.get().keySet();
    }

    @Override
    public Collection<V> values() {
        return internalMap.get().values();
    }

    @Override
    public Set<Entry<K, V>> entrySet() {
        return internalMap.get().entrySet();
    }

    @Override
    public int hashCode() {
        return internalMap.get().hashCode();
    }

    @Override
    public boolean equals(Object o) {
        return internalMap.get().equals(o);
    }

    @Override
    public String toString() {
        Map<K, V> map = internalMap.get();
        Iterator<Entry<K, V>> i = map.entrySet().iterator();
        if (!i.hasNext())
            return "{}";

        StringBuilder sb = new StringBuilder();
        sb.append('{');
        for (; ; ) {
            Entry<K, V> e = i.next();
            K key = e.getKey();
            V value = e.getValue();
            sb.append(key == this ? "(this Map)" : (key == map ? "(internal Map)" : key));
            sb.append('=');
            sb.append(value == this ? "(this Map)" : (value == map ? "(internal Map)" : value));
            if (!i.hasNext())
                return sb.append('}').toString();
            sb.append(',').append(' ');
        }
    }

    @Override
    public Object clone() {
        try {
            CopyOnWriteHashMap<K, V> clone = (CopyOnWriteHashMap<K, V>) super.clone();
            clone.internalMap = new AtomicReference<Map<K, V>>(new HashMap<K, V>(internalMap.get()));
            return clone;
        }
        catch (CloneNotSupportedException e) {
            throw new InternalError();
        }
    }
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/26202303

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档