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

标签 java multithreading concurrency

我确实陷入了并发 hell 。我无法找到一个好的/有效的解决方案来完成我想做的事情。我有一个生产者线程正在读取文本文件并将信息放入共享的 BlockedQueue 中。我有一个消费者,它使用共享的 BlockedQueue 来读取数据并对数据执行繁重的操作。我有一个带有三个按钮的 GUI:开始暂停停止

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

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

使用暂停选项,我希望生产者停止将数据放入BlockedQueue,但同时我希望能够访问生产者的实例变量。对于消费者来说也是如此,我想停止做繁重的事情,但仍然能够访问消费者中定义的一些实例变量和方法。

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

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

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

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
            }


        }
    }
}

最佳答案

My question is how to efficiently implement this? Especially to check for pause? Would something like this psudo-code be efficient?

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

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

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

The Producer and Consumer both implement Runnable and provide methods to access information about the computation of each one (e.g. return some statistics or some Objects)

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

My question is how to efficiently implement this? Especially to check for pause?

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

关于java - 如何启动、暂停和停止生产者/消费者关系?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19143522/

相关文章:

java - 如果它在生产环境中,调试死锁问题的正确行动计划是什么?

java - 在单独的线程中预创建对象

java - 在方法中使用 java.util.Scanner 会导致运行时错误

java - 即使主线程执行完成,Java应用程序如何继续运行?

java - java包在Eclipse中的位置

swift - 如何在后台线程中加载核心数据

java - syncAdapter、services、loaders、providers 和 asynctask 之间的混淆?

asynchronous - 在golang中,如何编写一个为下一阶段引入延迟的流水线阶段?

java - XPATH 问题。无法读取部分 html

java - MongoDB 嵌入式对象没有 ID(空值)