对于Java队列/列表,我如何原子地“排队,如果有空闲空间或出队然后入队”?

时间:2009-08-27 07:38:54

标签: java multithreading concurrency

我需要一个具有固定容量的Java列表,但它总是允许线程在开始时添加项目。如果它已满,则应从末尾移除一个项目以腾出空间。没有其他进程会删除项目,但其他进程将希望迭代项目。

JDK中有什么东西允许我原子地做这个吗?

我目前的计划是使用一些现有的线程安全集合(例如LinkedBlockingQueue),并在检查容量/添加/删除时进一步同步它。那还行吗?

感谢。

4 个答案:

答案 0 :(得分:1)

您的想法可行,但会涉及取出多重锁(请参阅下面的示例)。鉴于您在添加数据时需要同步多个操作,您也可以将LinkedList的{​​{1}}实现包装到以避免额外锁定的开销

Queue

答案 1 :(得分:0)

我正在使用Java的旧版本(是的1.3,我别无选择),所以即使它在以后的Javas中也存在,我也无法使用它。所以我按照以下方式编码:

public class Fifo  {
 private LinkedList fifoContents = new LinkedList();
 public synchronized void  put(Object element) {
     if ( fifoContents.size() > 100){               
          fifoContents.removeFirst();                
          logger.logWarning("*** Backlog, discarding messaage ");
     }
     fifoContents.add (element);
     return;
 }

 public synchronized Object get() throws NoSuchElementException {
     return fifoContents.removeFirst();
 }
}

答案 2 :(得分:0)

您可以在没有额外锁定的情况下完成测试/移除/插入:

class DroppingQueue<E>
extends ArrayBlockingQueue<E> {
    public boolean add(E item) {
        while (! offer(item)) {
            take();
        }
        return true;
    }
}

虽然此方法未同步,addoffer仍然存在,所以最糟糕的情况是线程#1将调用offer,发现队列已满,线程#2将执行相同的操作,并且在两个线程成功添加项目之前,两者都将删除项目,暂时将项目数量减少到小于最大值。这可能不会导致严重的问题。

答案 3 :(得分:0)

JDK中没有这样的课程。 如果你要实现这样的集合,你可能想要使用带浮动头/尾指针的数组 - 因为你有固定的大小,你根本不需要链表。