并发收集到50/50读/写

时间:2014-11-25 09:29:42

标签: java multithreading collections concurrency

我需要你的建议。首先,我想描述一些先决条件。

  1. 我有一些第三方Java对象,默认java.lang.Object hashCode()equals()实现。 Comparable接口未实现。尺寸微不足道。
  2. 我需要在内存中存储这些对象一段时间。我将以50/50的比例从不同的线程中读取和写入它们(大约50%读取和50%写入)。
  3. 对象的顺序并不重要。我只是想有可能从商店拿一些物品,这就是全部。 我的意思是同时获取删除
  4. 当然,我希望它能以最低的内存消耗尽可能快地工作。我试图避免在我的代码中进行任何同步。
  5. 首先,我试图自己解决这个问题。由于内存消耗过高,我立即拒绝了CopyOnWriteArray*个收藏集。我认为在罕见的写入情况下使用它们会更好。 ConcurrentHashMap在一般套件中满足我的需求,但我没有找到方法在没有同步的情况下使采取操作原子。我对ConcurrentSkipListSet收集的调查已经停止了。它包含pollFirst方法,非常适合获取对象。

    我以ConcurrentSkipListSet为基础实施了我的解决方案。除了一个小细节之外我一切正常。正如我上面提到的那样,我正在努力实现Comparable。因此,要使用所选集合,我必须以某种方式实现Comparator。这是我对此界面的实现。在此示例中,我直接使用java.lang.Object而不是我的对象类型。我已经做到了这一点,因为实现完全相同,不同之处仅在于类的通用部分。

    import java.util.Comparator;
    
    public class ObjectComparator implements Comparator<Object> {
    
        public int compare(Object o1, Object o2) {
            return o1.hashCode() - o2.hashCode();
        }
    }
    

    这种实现的缺点是显而易见的。我发现那里有no guarantee两个不同的对象会有不同的哈希码。在这种情况下,可能会丢失一些不可接受的物体。我想在不同对象的哈希码相同的情况下返回一些随机数,但我不确定它是否会破坏ConcurrentSkipListSet实现。

    关于描述的情况,我有两个一般性问题。

    1. 是否可以为我的对象实施Comparator,以便不为不同的对象返回0并保持ConcurrentSkipListSet可操作性?
    2. 还有其他方法来存储我的物品吗?
    3. 提前感谢您的回答。

3 个答案:

答案 0 :(得分:3)

可能您正在寻找ConcurrentLinkedQueue,这将根据FiFo(先进先出)订单存储商品。因此,不存在hashcodecomparable要求。这个队列的实现非常有效,没有任何内部锁定。

你有一个难点(不使用锁)是你无法检查集合是否为空,然后取一个(因为它可能在你的检查之后和你的行动之前已经改变)。因此,take函数将在没有任何内容时返回null。如果您不想继续轮询数据,那么您也可以使用实现BlockingQueue接口的类,这提供了等待数据可用的函数。

答案 1 :(得分:1)

1:你可以这样实现你的比较器:

public int compare(Object o1, Object o2) {
    if (o1 == o2) {
        return 0;
    } else {
        int dif = o1.hashCode() - o2.hashCode();
        if (dif != 0) {
            return dif;
        } else {
            return 1; //Might cause issues
        }
    }
}

2:您可以使用java.util.Collections.synchronizedCollection()(或任何其他同步方法)使任何正常集合同步。例如,如果您同步LinkedList,则可以使用remove(index)来获取对象。

答案 2 :(得分:1)

  

ConcurrentHashMap在一般套件中满足我的需求,但我没有找到制作采取操作原子的方法

为什么不在ConcurrentHashMap中使用remove?似乎这就是你所需要的。