如何使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;
...
}
并在需要时委托支持集合。当然,你需要得到Conditions和Lock。
另一答案
您必须实际编写自己的队列实现。由于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线程安全?的主要内容,如果未能解决你的问题,请参考以下文章