在某种方式同步Map上使用guava的MapConstraint

时间:2011-02-07 14:39:38

标签: java map synchronization guava

使用Guava,我希望有一个具有以下属性的地图:

  • 很多读,但很少写。
  • 数据不会过期。
  • 必须同步,因此写入是“原子的”,多次读取不会相互干扰。
  • 地图应该使用MapConstraint API,其中一些MapConstraint是针对地图本身的内容(通常如果记录或其他内容存在,请不要覆盖它:抛出{{{ 1}}而不是)。我看到IllegalStateException界面未对MapConstraint进行约束。
  • Map的检查必须在同步部分内完成。

我已经考虑过使用MapConstraint,但我想知道ReadWriteLock是否可以帮助我,因为我对这个API不是很熟悉。

那么我的选择是什么?


编辑:我的目标不是一个简单的MapMaker:我需要在插入值之前对地图执行几次检查,总是在同步写入中。

2 个答案:

答案 0 :(得分:1)

我不确定您是否可以使用 MapConstraint 语义轻松完成此操作。你可以让MapConstraint知道底层地图,在构造过程中传递一个对地图的引用:

MapConstraints.constrainedMap(map, new MyCustomMapConstraint(map));

但它会很丑/有风险。有人可能会错误地做:

MapConstraint constraint = new MyCustomMapConstraint(firstMap);
Map constrainedMap = MapConstraints.constrainedMap(secondMap, constraint);

另外,它无法解决同步问题。


如果我这样做,我会使用ConcurrentMap提供的“putIfAbsent”方法。我将使用ForwardingConcurrentMap:

创建一个ConcurrentMap包装器
public class ProtectionistMap<K, V> extends ForwardingConcurrentMap<K, V> {

    private final ConcurrentMap<K, V> delegate;

    public ProtectionistMap(ConcurrentMap<K, V> delegate) {
        this.delegate = checkNotNull(delegate);
    }

    @Override
    protected ConcurrentMap<K, V> delegate() {
        return delegate;
    }

    @Override
    public V put(K key, V value) {
        V result = putIfAbsent(key, value);

        // The second part of the test is necessary when a map may contain null values...
        if (result != null || value == null && containsKey(key)) {
            throw new IllegalArgumentException("Map already had an entry for key " + key);
        }
        return result;
    }

    @Override
    public void putAll(Map<? extends K, ? extends V> map) {
        standardPutAll(map);
    }
}

答案 1 :(得分:0)

我的回答根本不是关于番石榴,但为什么不考虑使用java.util.concurrent.ConcurrentHashMap?除了直接支持MapConstraint之外,它还拥有您所需要的一切。

如果存在记录,则可以使用containsKey()方法,而不是抛出异常。 或者,如果您需要异常,只需创建自己继承自ConcurrentHashMap的类。如果你真的需要它,它也可以使用MapConstraint。 看起来像2分钟的工作,代码将如下所示:

public V put(K key, V value) {
    if (value == null)
        throw new NullPointerException();
    int hash = hash(key.hashCode());
    Segment seg = segmentFor(hash);
    V result;
    seg.lock()
    try {
        constraint.checkKeyValue(key, value);
        v = seg.put(key, hash, value, false)
    } finally {
        seg.unlock()
    }
    return result;
}

不要从字面上理解这个代码,这只是一个例子;)

如果您需要有关ConcurrentHashMap内部的更多信息,可以在这里查看: ConcurrentHashMap revealed