2012-03-21 69 views
1

我想,和失败,在Java中实现生产者消费者模式,受到以下限制:生产者消费者在Java中有一个UI切换

  • 生产者生产地(并在消费者从消费)一个队列具有有限大小
  • 没有与按钮切换生产者和消费者,分别
  • 当队列不满生产者按钮被切换活性生产者只应产生的用户界面,
  • 只有当队列不为空时,消费者才会消耗消费者按钮处于活动状态。
  • 生产和消费都应该可以同时进行。 (事实上​​,有生产将至少尽可能消耗,有时更快。)

我的想法是为执行缓冲器为有限大小的的LinkedBlockingQueue,以处理与所述队列中的条件空/满状态 - 当试图放入一个完整的队列或从一个空队列取出时应该阻塞。然后,在生产者和消费者上使用布尔状态,触发按钮。最后,在生产者和消费者中使用while/wait /循环,并在代码中通知按钮。

类似下面,对于制片方:

while (true) { 
    if (!producing) { wait(); } 
    // generate a bunch of data and and finally   
    // Save this chunk of data 
    buffer.addData(data); 
    } 

而且在生产者按钮的代码中,我们既切换生产状态,并调用一个方法在生产者自我通知。

问题:一旦生产者正在生产,即使用户界面(在Swing中实现)也失去响应性,他们的轮询非常困难。我可以通过填写wait(1);声明来解决这个问题,但是出于各种不可接受的原因,这是不可接受的。有些延迟是不可避免的,但是每次通过循环1毫秒的延迟都不起作用。

我也不相信我对LinkedBlockingQueue有正确的理解,因为如果我让队列填满,我仍然失去了UI响应。我清楚地误解了Java中运行的操作,因为我尝试了多种方法,而且这是最接近的;先前的方法试图在没有LinkedBlockingQueue的情况下“手动”处理满/空条件是可悲的失败。

任何意见,将不胜感激。当然,我试图做的事情(锁定两个条件而没有过多的投票)并非不可能,是吗?

回答

4

discussion包括程序TwoTimer,其中javax.swing.Timer递增一个int在100Hz,而java.util.TimerTask样品在1Hz的值。变体将样本存储在LinkedBlockingQueue中,形成最近的历史队列。它与您的任务没有直接关系,但它说明了响应式GUI的基本要求:从不阻止事件派发线程。该示例使用invokeLater()执行下一个收集。

还考虑nextGaussian()模拟延迟,如图所示here

顺便说一下,您可能会喜欢这个动画为几何形状队列的example

2

你所描述的应该可以正常工作。发布你的实际代码(抽象出实际生产和实际消费)将会有所帮助。你说

它轮询这么辛苦甚至UI失去响应

,这似乎意味着你是滥用的LinkedBlockingQueue。您不应该反复轮询队列。您应该从队列中取出一个项目,处理它,然后检查生产标志,并在UI调用notifyAll()的监视器上生成和排队项目,或wait()。

+0

但生产和消费**可能同时启用,但它们不是**必需**。所以生产只能在没有消费的情况下启用。我明天会更新附加的代码。 – Novak 2012-03-21 06:16:46