如何启动,暂停和停止生产者/消费者关系?

时间:2013-10-02 17:54:41

标签: java multithreading concurrency

我绝对是一个并发的地狱。我无法为我正在尝试的事情找到一个好的/有效的解决方案。我有一个正在读取文本文件的Producer线程,并将信息放在共享的BlockedQueue中。我有一个消费者,它使用共享的BlockedQueue来读取数据,并对数据做了大量工作。我有一个带有三个按钮的GUI:开始暂停停止

Producer和Consumer都实现Runnable并提供访问每个计算信息的方法(例如返回一些统计信息或一些对象)

使用开始选项,我希望Producer打开文件并开始将数据放入BlockedQueue。消费者也开始获取数据并进行计算。

使用 Pause 选项,我希望Producer停止将数据放入BlockedQueue,但同时我希望能够访问Producer的实例变量。同样适用于消费者,我想停止做重物但仍然能够访问消费者中定义的一些实例变量和方法。

使用停止选项,我希望生产者和消费者重置...即好像从干净开始。

我的问题是如何有效地实现这个?特别要检查暂停?

像这样的psudo代码会有效吗?

Enum state;

class Producer implements Runnable {
    public List someList;//accessed from the event-dispatching thread 
    public void Run() {
        synchronized(state) {
            if(state == Enum.paused) {
                //do nothing
            }
            else if(state == Enum.running) {
                //put stuff into BlockedQueue
            }
            else if (state == Enum.stopped) {
               // reopen file and set state = running
            }


        }
    }
}

class Consumer implements Runnable {
    public Map someMap;//accessed from the event-dispatching thread 
    public void Run() {
        synchronized(state) {
            if(state == Enum.paused) {
                //do nothing
            }
            else if(state == Enum.running) {
                //start consuming from the BlockedQueue and do heavy computation
            }
            else if (state == Enum.stopped) {
               // clear stuff to start clean and set state = running
            }


        }
    }
}

2 个答案:

答案 0 :(得分:1)

  

我的问题是如何有效地实现这个?特别要检查暂停?这样的psudo代码会有效吗?

我认为使用ConsumerProducer上的字段是一种很好的方法。您需要确保该字段为volatile,以便在线程之间正确同步枚举的任何更新。或者,如果您使用synchronized关键字,则在更新时需要synchronizedvolatile在这种情况下更好,因为没有理由阻止。

 public class Consumer {
    private volatile Enum state;
    ...
    if(state == Enum.paused) {

人们已经提到了一种毒丸"作为解决方案。将对象放入更改状态的队列时。这个解决方案的问题在于,如果消费者正在处理该对象,它就不会检查队列,因此这不会起作用。我猜你可以peek()在队列中,但state字段可以正常工作。

  

Producer和Consumer都实现Runnable并提供访问每个计算信息的方法(例如返回一些统计信息或一些对象)

ProducerConsumer对象仍然存在且可以访问。在所有情况下,您需要确保对线程之间共享的字段所做的任何更新都需要正确同步。

  

我的问题是如何有效地实现这个?特别要检查暂停?

就效率而言,volatile字段访问似乎比典型的字段访问慢约100倍。我不会对每一行进行状态检查,但是如果你在每个处理循环的顶部检查它,或者做if (loopCounter % 1000 == 0)之类的事情来检查循环中每X次暂停一次,你就不应该这样做。如果有任何表现受到影响,那就太多了。

答案 1 :(得分:0)

您可以标记进入队列的消息,无论它们是数据消息还是控制消息。每个线程只有一个输入(消息)队列。