【问题标题】:Can we use blockingqueue to implement circular buffer我们可以使用blockingqueue来实现循环缓冲区吗
【发布时间】:2011-04-12 23:24:06
【问题描述】:

需要一个循环的 FIFO 缓冲区(如果队列已满,总是删除最先的项),我们可以使用阻塞队列来实现吗?

【问题讨论】:

  • BlockingQueue 只是用于多线程模式的Queue。为什么不只是一个Queue

标签: java


【解决方案1】:

是的。见ArrayBlockingQueue

public class ArrayBlockingQueue<E>
extends AbstractQueue<E>
implements BlockingQueue<E>, Serializable

由一个有界阻塞队列支持 大批。此队列将元素排序为 FIFO (先进先出)。团长 queue 是那个元素 排队时间最长。尾巴 队列的元素是具有 排队时间最短。 在尾部插入新元素 队列和队列检索 操作在头部获取元素 队列。

这是一个经典的“有界缓冲区”,在 一个固定大小的数组持有 生产者插入的元素和 被消费者提取。一旦创建, 容量不能增加。 尝试将元素置于完整状态 queue 将导致 put 操作 阻塞;尝试检索 来自空队列的元素将 同样挡住。

【讨论】:

  • 我的问题是当队列已满时,可以把方法去掉头部并自动插入尾部吗?
  • 自动:没有。但是你可以使用offer(),如果失败了,你自己取下头部再试一次。
【解决方案2】:

这可能会有所帮助:这是一个线程安全的解决方案,其中 ArrayBlockingQueue 用作具有这些约束的循环环形缓冲区:

  1. 生产者:应该始终能够将数据放入缓冲区而不会被阻塞,即使缓冲区已满(即满时从头部删除!)。 虽然如果我们希望生产者也被阻止,那么它很简单!

  2. 消费者:应该能够从输入中获取缓冲区,如果它为空,则应该被阻塞(如果你也希望它是非阻塞的,可以使用 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()
    ..
    

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-04-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多