【发布时间】:2011-04-12 23:24:06
【问题描述】:
需要一个循环的 FIFO 缓冲区(如果队列已满,总是删除最先的项),我们可以使用阻塞队列来实现吗?
【问题讨论】:
-
BlockingQueue只是用于多线程模式的Queue。为什么不只是一个Queue?
标签: java
需要一个循环的 FIFO 缓冲区(如果队列已满,总是删除最先的项),我们可以使用阻塞队列来实现吗?
【问题讨论】:
BlockingQueue 只是用于多线程模式的Queue。为什么不只是一个Queue?
标签: java
是的。见ArrayBlockingQueue:
public class ArrayBlockingQueue<E> extends AbstractQueue<E> implements BlockingQueue<E>, Serializable由一个有界阻塞队列支持 大批。此队列将元素排序为 FIFO (先进先出)。团长 queue 是那个元素 排队时间最长。尾巴 队列的元素是具有 排队时间最短。 在尾部插入新元素 队列和队列检索 操作在头部获取元素 队列。
这是一个经典的“有界缓冲区”,在 一个固定大小的数组持有 生产者插入的元素和 被消费者提取。一旦创建, 容量不能增加。 尝试将元素置于完整状态 queue 将导致 put 操作 阻塞;尝试检索 来自空队列的元素将 同样挡住。
【讨论】:
offer(),如果失败了,你自己取下头部再试一次。
这可能会有所帮助:这是一个线程安全的解决方案,其中 ArrayBlockingQueue 用作具有这些约束的循环环形缓冲区:
生产者:应该始终能够将数据放入缓冲区而不会被阻塞,即使缓冲区已满(即满时从头部删除!)。 虽然如果我们希望生产者也被阻止,那么它很简单!
消费者:应该能够从输入中获取缓冲区,如果它为空,则应该被阻塞(如果你也希望它是非阻塞的,可以使用 poll())。
//模拟环形缓冲区
BlockingQueue<Short[]> bufferQueue = new ArrayBlockingQueue<Short[]>(MAX_SIZE);
Producer Code:
...
//not using put() directly as it can block this thread forever
if(!bufferQueue.offer(buffer)){
//retrieve and remove the head of the queue to make space for this buffer
//don't use take() as it can block this thread again if consumer took all
//the data before call to take()!
bufferQueue.poll();
//now put can be used safely, remember there is only one producer!
bufferQueue.put(buffer);
}
...
Consumer Code:
..
//this will block till buffer is empty
//can use .poll() if don't want blocking call
bufferQueue.take()
..
【讨论】: