在Java中,如何更改ArrayBlockedQueue的长度?

在Java中,如何更改ArrayBlockedQueue的长度?,java,android,concurrency,Java,Android,Concurrency,我正在为Android创建一个媒体播放器应用程序。我有两个线程:一个生成音频帧,另一个使用这些帧 我希望我的客户能够尝试使用不同大小的ArrayBlockedQueue,从“无”缓冲(实际上是1)到最多10个缓冲块 我在Java中似乎找不到任何类提供与ArrayBlockedQueue类似的功能,但允许我动态地使项目列表变长/变短 问题1)是否有人知道一个类的功能类似于ArrayBlockedQueue,但允许我更改要保存的项目数量 然后我有一个奇怪的想法:我能捏造它吗?我是否可以创建一个具有新

我正在为Android创建一个媒体播放器应用程序。我有两个线程:一个生成音频帧,另一个使用这些帧

我希望我的客户能够尝试使用不同大小的ArrayBlockedQueue,从“无”缓冲(实际上是1)到最多10个缓冲块

我在Java中似乎找不到任何类提供与ArrayBlockedQueue类似的功能,但允许我动态地使项目列表变长/变短

问题1)是否有人知道一个类的功能类似于ArrayBlockedQueue,但允许我更改要保存的项目数量

然后我有一个奇怪的想法:我能捏造它吗?我是否可以创建一个具有新大小的新ArrayBlockedQueue,并逐步复制当前位于旧ArrayBlockedQueue中的1-10个项目,将它们放入新ArrayBlockedQueue,然后在旧ArrayBlockedQueue上存储指向新ArrayBlockedQueue的指针

由于缓冲区的数量永远不会超过10个(或者我的缓冲区限制是多少),所以将项目复制到新数组中不会花费太多时间

问题2)这是一种“合理”的方法来处理ArrayBlockedQueue实现,它仍然给了我灵活性吗

问题3)有没有更好的方法来解决这个问题

-肯

回答您的问题:

1) 虽然LinkedBlockingQueue之类的东西会增长到您为其设置的最大值,但没有一个允许您手动更改队列大小的工具

2和3)您可以使用文档中描述的第三个构造函数执行所述操作(创建新的ArrayBlockingQueue):

ArrayBlockingQueue(整数容量、布尔公平、集合c)

创建具有给定(固定)容量、指定访问策略和的ArrayBlockingQueue,该队列最初包含给定集合的元素,并按集合迭代器的遍历顺序添加

这将为您提供所需的拷贝构造,并允许您设置新容量。评估:

// create the first queue
Queue smallQueue = new ArrayBlockingQueue(5);

// copy small queue over to big queue
Queue bigQueue = new ArrayBlockingQueue(10, false, smallQueue);
向下调整大小(伪代码):


步骤1中的PUT将被阻止,直到您切换消费者。

您可能需要创建自己的
BlockingQueue
实现来包装旧队列和新队列-从旧队列轮询,直到其为空,然后将其设置为null以防止任何内存泄漏。这样,您就不会丢失旧队列上任何挂起的
put
s

MyBlockingQueue {
  private MyBlockingQueue oldQueue
  private ArrayBlockingQueue newQueue

  ArrayBlockingQueue(int newCapacity, MyBlockingQueue _oldQueue) {
    oldQueue = _oldQueue
    newQueue = new ArrayBlockingQueue(newCapacity)
    E oldVal = null
    while(newQueue.remainingCapacity() > 0 && 
         (oldVal = oldPoll) != null)
      newQueue.put(oldVal)
  }

  boolean isEmpty() {
    (oldQueue == null || oldQueue.isEmpty) && newQueue.isEmpty 
  }

  void put(E e) {
    newQueue.put(e)
  }

  E take() {
    E oldVal = oldPoll
    if(oldVal != null) oldVal else newQueue.take
  }

  E poll() {
    E oldVal = oldPoll
    if(oldVal != null) oldVal else newQueue.poll
  }

  private E oldPoll() {
    // If you have more than one consumer thread, then use a temporary variable
    // for oldQueue - otherwise it might be set to null between the null check
    // and the call to poll
    if(oldQueue == null) null
    else {
      E oldVal = oldQueue.poll
      if(oldVal != null) oldVal
      else {
        oldQueue = null
        null
      }
    }
  }
}

你能不能查一下并基于它添加?我使用队列的阻塞容量作为协调我的两个线程的输入和输出的东西。我非常希望挂起任何挂起的put()或take()调用。如果我理解你的意思,put()就不会挂起…它就是不会被挂起。现在/那很有趣。这允许我增加缓冲区的最大大小…我可以提交注释。正如我刚才所说的,这让我可以增加缓冲区……但是减少缓冲区又如何呢?如果我的用户决定关闭缓冲(将队列中的项减少到1项),我希望发生的是任何put()都被阻塞,队列正常清空,当容量降低到所需的水平时,我可以复制它,最后完成put()calls.Hrm…确定问题所在…我看不到一种方法来确定是否有任何put()调用挂起,也看不到一种方法来将它们转移到新队列。哎哟。这太离谱了,但我会创建一个新的队列,大小为1,并将您的生产者和消费者指向它。现在没有任何内容将进入旧队列,但它可能不是空的。在旧队列上调用一次drainTo(),那么您应该很好。编辑:我明白了问题所在,是的,如果你有潜在的阻塞看跌期权备份,你需要进行投票,直到队列为空。是的,我明白你的意思。一个很好的大伪代码解释。谢谢你抽出时间来齐姆赞!(我不知道为什么Slashdot的通知程序向我的收件箱发送了16条关于你回复的消息……也许它只是对此感到非常兴奋?)
MyBlockingQueue {
  private MyBlockingQueue oldQueue
  private ArrayBlockingQueue newQueue

  ArrayBlockingQueue(int newCapacity, MyBlockingQueue _oldQueue) {
    oldQueue = _oldQueue
    newQueue = new ArrayBlockingQueue(newCapacity)
    E oldVal = null
    while(newQueue.remainingCapacity() > 0 && 
         (oldVal = oldPoll) != null)
      newQueue.put(oldVal)
  }

  boolean isEmpty() {
    (oldQueue == null || oldQueue.isEmpty) && newQueue.isEmpty 
  }

  void put(E e) {
    newQueue.put(e)
  }

  E take() {
    E oldVal = oldPoll
    if(oldVal != null) oldVal else newQueue.take
  }

  E poll() {
    E oldVal = oldPoll
    if(oldVal != null) oldVal else newQueue.poll
  }

  private E oldPoll() {
    // If you have more than one consumer thread, then use a temporary variable
    // for oldQueue - otherwise it might be set to null between the null check
    // and the call to poll
    if(oldQueue == null) null
    else {
      E oldVal = oldQueue.poll
      if(oldVal != null) oldVal
      else {
        oldQueue = null
        null
      }
    }
  }
}