如何使CircularFifoQueue线程安全?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何使CircularFifoQueue线程安全?相关的知识,希望对你有一定的参考价值。

我想用CircularFifoQueue和春天的ExecutorService

以下不编译,因为CircularFifoQueue不是BlockingQueue类型。但它显示了我想要实现的目标:

int threads = 10;
int queueSize = 500;
new java.util.concurrent.ThreadPoolExecutor(threads, threads, 0L, TimeUnit.MILLISECONDS, 
                new CircularFifoQueue(queueSize));

附:

package org.apache.commons.collections4.queue;

public class CircularFifoQueue<E> extends AbstractCollection<E>
       implements Queue<E>, BoundedCollection<E>, Serializable

问题:上面的代码是否提供了线程安全性(因为CircularFifoQueue本身不是线程安全的)?如果没有,我怎么能让它线程安全?

答案

工作队列意味着阻塞,因此你需要添加一个decorator来使CircularFifoQueue成为BLockingQueue

class BlockingCircularFifoQueue<E> implements BlockingQueue<E>{
  private CircularFifoQueue<E> backingCollection;
  ...
} 

并在需要时委托支持集合。当然,你需要得到ConditionsLock

另一答案

您必须实际编写自己的队列实现。由于CircularFifoQueue使用底层数组来保存元素,因此我将以java.util.concurrent包中的ArrayBlockingQueue数据结构作为起点。

示例:

class ThreadSafeCircularFifoQueue<T> extends CircularFifoQueue<T> implements BlockingQueue<T> {

    /** Main lock guarding all access */
    final ReentrantLock lock;

    /** Condition for waiting takes */
    private final Condition notEmpty;

    /** Condition for waiting puts */
    private final Condition notFull;

    @Override
    public int size() {

        final ReentrantLock lock = this.lock;
        lock.lock();
        try {
            return super.size();
        } finally {
            lock.unlock();
        }
    }

    //and so forth
}
另一答案

您可以使用commons-collections QueueUtils.synchronizedQueue进行同步

Queue queue = QueueUtils.synchronizedQueue(new CircularFifoQueue());

但根据javadoc,它需要额外的串行访问同步:

为了保证串行访问,必须通过返回的队列完成对后备队列的所有访问。

当迭代时,用户必须手动同步返回的队列:

Queue queue = QueueUtils.synchronizedQueue(new CircularFifoQueue());
...
synchronized(queue) {
    Iterator i = queue.iterator(); // Must be in synchronized block
    while (i.hasNext())
        foo(i.next());
    }
}

不遵循此建议可能会导致非确定性行为。

以上是关于如何使CircularFifoQueue线程安全?的主要内容,如果未能解决你的问题,请参考以下文章

如何使 ObservableCollection 线程安全?

如何轻松使 std::cout 线程安全?

如何使 Stack.Pop 线程安全

如何使这个线程安全

如何使 Swift 类单例实例线程安全?

如何使用 Platform.runLater 使 JavaFX 线程安全