0

我绝对处于并发地狱中。我无法为我正在尝试做的事情找到一个好的/有效的解决方案。我有一个生产者线程正在读取文本文件并将信息放入共享的 BlockedQueue。我有一个消费者,它使用共享的 BlockedQueue 来读取数据并对数据进行繁重的处理。我有一个带有三个按钮的 GUI:StartPauseStop

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

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

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

使用Stop选项,我希望 Producer 和 Consumer 重置 ... 即好像从干净开始。

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

这样的伪代码会有效吗?

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
            }


        }
    }
}
4

2 回答 2

1

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

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

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

人们提到了“毒丸”作为解决方案。当你将一个对象放入队列时,它会改变状态。这个解决方案的问题是,如果消费者正在处理对象,它不会检查队列,所以这不起作用。我想您可以peek()在队列中,但该state字段应该可以正常工作。

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

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

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

就效率而言,volatile字段访问似乎比典型的字段访问慢约 100 倍。我不会对每一行都进行状态检查,但是如果您在每个处理循环的顶部检查它,或者在if (loopCounter % 1000 == 0)循环中每隔 X 次检查一次暂停,您应该不会看到太多性能受到影响。

于 2013-10-02T18:54:12.083 回答
0

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

于 2013-10-02T18:10:06.930 回答