java:并发集合

标签 java concurrency map guava

我试图找到一个或多个并发集合来使用,我可以实现以下行为(名称是出于类比目的而设计的):

/**
 * Acts as a broker for a concurrent hash map that stores its keys in order 
 * of submission. At shipping time, the concurrent map is "sealed" 
 * (picture a truck with its cargo door being closed)
 * and its contents presented as an immutable map, and is replaced 
 * by a new concurrent map ready to accept values.
 *
 * Consumers of this class that submit information to it, are expected to 
 * know that this contains a concurrent collection, and should use the 
 * compareAndSet paradigm, e.g. the following:
 *
 * LoadingDock loadingDock = ...
 * boolean done = false;
 * while (!done)
 * {
 *    V oldValue = loadingDock.get();
 *    V newValue = computeNewValue(oldValue, otherInformation);
 *    if (oldValue == null)
 *       done = loadingDock.putIfAbsent(newValue) == null;
 *    else
 *       done = loadingDock.replace(oldValue, newValue) == oldValue;
 * }
 *    
 *
 * Keys and values must be non-null. Keys are not ordered.
 */
class LoadingDock<K,V>
{
    /**
     * analogous to ConcurrentMap's replace, putIfAbsent, and get methods
     */
    public boolean replace(K key, V oldValue, V newValue);
    public V putIfAbsent(K key, V value);
    public V get(K key)

    /* see above */
    public Map<K,V> ship();
}

我有两个问题。

一个是 Java 和 Guava 都不包含 ConcurrentLinkedHashMap。这让我想知道为什么不——也许我错过了这样一个野兽的微妙之处。看起来我可以通过用一个类装饰 ConcurrentHashMap 来自己制作一个,如果 putIfAbsent() 被调用并返回 null 则向列表添加一个键——我不需要任何ConcurrentHashMap 中除上述方法之外的其他方法,因此除了调用 putIfAbsent() 之外,无法向映射添加新键。

另一个更隐蔽的问题是,我似乎想不出如何在不阻塞同步的情况下实现 ship()——当调用 ship() 时,LoadingDock 需要直接对新 map 的所有新调用,并且在确定所有并发写入完成之前不能返回旧 map 。 (否则我只会使用 AtomicReference 来保存并发映射。)

有没有办法在不需要同步的情况下做到这一点?

最佳答案

你可以使用 ConcurrentSkipListMap并提供您自己的比较器,根据时间戳对条目进行排序。人们想象没有 ConcurrentLinkedMap,因为没有任何比同步常规方法好得多的特别好的方法来实现它。

对于 ship() 方法,只需使用 ReadWriteLock开启了公平模式。想要添加到 map 的线程,获取读取锁(我知道奇怪的语义,但它是如何工作的,将其视为实际引用 map 的读取模式,然后正常使用)以便尽可能多可以同时添加。在 ship 方法中,您获得了写锁,它会阻止任何其他人在您导出和创建新 map 时更改 map 。公平模式使您可以在调用 ship() 时尽可能地“切断”加法器,并让现有的加法器完成。

关于java:并发集合,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9215418/

相关文章:

java - 将按键发送到 JTextField

java - 如何在集群模式下运行docker redis?

go - 测试信号量实现时出错

java - JAX-RS,Map<String,String> 到 JSON 没有开销?

java - 如何为 nattable 中的某些列设置自定义样式?

java - 玩2.1 SSL配置

c++ - 默认情况下,std::vector 是线程安全和并发的吗?为什么或者为什么不?

java - 信号量 : Permit acquired in one thread can be released from another thread - Example

java - 使用按值传递创建 Map 副本的最佳方法是什么?

C++ 映射迭代器问题