什么是允许Collections.sort的线程安全List实现

时间:2016-08-22 07:00:02

标签: java sorting collections concurrency

我必须编写一个需要列表的程序。此列表在其实现中需要是线程安全的(主要是为了避免ConcurrentModificationException),但是ALSO需要允许 出于API原因,要应用Collections.sort()方法。

CopyOnWriteArrayList实现了前者,但不是后者,我能找到的其他实现允许后者而不是前者。

Java是否有适合我的列表实现?

编辑:需要注意的一点是,遗憾的是我的代码需要与Java 6兼容。

2 个答案:

答案 0 :(得分:4)

我想知道这在概念层面上是否真的可行:为了使 sort 操作保持一致,我希望整个列表可以阻止任何添加/在排序进行时删除。

但Collections.sort()不知道在完成工作时需要锁定整个列表。你给它一个列表,如果另一个线程试图同时修改列表...祝你好运。

或者如果你颠倒了观点:一个"线程安全"列表明白它现在正处于排序过程中;所以 - 一些访问(如交换元素)很好;但其他(如添加/删除)元素不是?!

换句话说:我认为你只能做到这一点:选择任何一个"线程安全的"列表实现;然后你必须把你自己的包装放到

  1. "锁"更改列表
  2. 排序是否正常工作
  3. "解锁"清单
  4. 当然,对于" 2。&#34 ;;你可以自由转向Collections.sort()。

    或者,如果您使用的是Java8 - 您可以使用CopyOnWriteArrayList及其已经实现的sort()方法(这有点证明了我的观点:如果,您只能进行正确的排序在运行排序操作时拥有列表!)。

    发表您的最新评论:当然,您可以手动" backport"将CopyOnWriteArrayList的Java8版本导入您的环境并使用它;但当然,这不会有所帮助;据我所知,Java6-Collections.sort()将从该类调用新的sort()方法。

    所以,似乎你的要求总和无法解决;而且你必须咬紧牙关并在自己的代码中完成大部分工作。

答案 1 :(得分:2)

好吧,CopyOnWriteArrayList在排序时锁定整个集合(用于插入)。否?

看起来你对CopyOnWriteArrayList很满意。以下是此课程的片段 -

public void sort(Comparator<? super E> c) {
    final ReentrantLock lock = this.lock;
    lock.lock();**
    try {
        Object[] elements = getArray();
        Object[] newElements = Arrays.copyOf(elements, elements.length);
        @SuppressWarnings("unchecked") E[] es = (E[])newElements;
        Arrays.sort(es, c);
        setArray(newElements);
    } finally {
        lock.unlock();
    }
}

嗯....因为您已经更新了代码需要与Java6兼容的问题,我要说您应该扩展正常列表并使用https://docs.oracle.com/javase/6/docs/api/java/util/concurrent/locks/ReadWriteLock.html。在这种类型的锁中,即使某些其他线程已经获得了writeLock,读者也不会被阻止阅读,并且2个线程可以获得“读取”。同时锁定。

顺便说一句,这种技术将要求你的调用者知道不应该调用Collection.sort(...),因为你必须在列表中公开显式的sort()方法。嗯....不确定这是否有用。