Java - 在远程/ take上排序的线程安全集合

时间:2014-03-24 17:59:05

标签: java multithreading collections queue

我有一种情况,我需要一个线程安全队列,每次调用remove()方法时都会运行一个排序,并且只有在调用该方法时才会运行。这是因为在外部因素将对象添加到集合后,对象可以动态更改“优先级”。这也需要线程安全。没有必要扩展像PriorityBlockingQueue这样的东西,因为它会在添加时运行比较函数。我没有找到任何这样的集合/队列,所以我试图通过只包裹一个数组列表来实现我自己的:

public class BlockingSortOnTakeQueue<E> implements Queue<E>
{
    private ArrayList<E> m_list;

    public BlockingSortOnTakeArrayList()
    {
        m_list = new ArrayList<>();
    }


    @Override
    public synchronized E remove() 
    {
        m_list.sort(m_comparator);
        return m_list.remove(0);
    }

    ....

不幸的是,我很难弄清楚如何确保对象类型<E>必须实现可比较的接口,并在尝试对列表进行排序时使用该对象compareTo函数(在代码中我有m_comparator这是未完成/占位符。)

有没有人知道只对remove()进行排序的线程安全队列,或者如何修复自定义集合的开头,以便使用通用对象compareTo函数对列表进行排序。

2 个答案:

答案 0 :(得分:2)

看起来你按照必须这样做的方式去做。要强制Comparable接口,请写

public class BlockingSortOnTakeQueue<E extends Comparable<E>> implements Queue<E> {
  ...
  @Override
  public synchronized E remove() {
    Collections.sort(m_list);
    return m_list.remove(0);
  }
}

...虽然使用Collections.sort(m_list, Collections.reverseOrder())以相反顺序排序可能对您有利,并删除最后一个元素,因为ArrayList中的速度更快。

最好只识别最小元素,而不是整列整个列表,这可能是O(n)而不是O(n log n)。

答案 1 :(得分:0)

  

对象可以动态地改变&#34; priority&#34;由于外部因素将它们添加到集合中之后。这也需要线程安全。

那么,如果那些&#34;外部因素&#34;会发生什么?在排序算法运行时更改集合中的对象?它可能会破坏列表,并且您的示例代码不会显示您是如何阻止它发生的。那些&#34;外部因素&#34;如果你想避免这个问题,必须在remove()函数的同一个对象上同步。

此外,如果您的代码成功删除了优先级最高的项目,那么它会导致您的问题,然后,在您可以执行任何您正计划使用它的任何事情之前,它会导致问题,一个&#34;外部因素&#34;运行,并导致仍在集合中的其他对象具有更高的优先级?如果是这样,那么你不需要同步remove()函数,而是需要同步调用remove(),执行操作的任何代码块。