我确实陷入了并发 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?
我认为在 Consumer
和 Producer
上使用字段是实现此目的的好方法。您需要确保该字段是 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)
Producer
和 Consumer
对象仍然存在并且可以访问。在所有情况下,您都需要确保对要在线程之间共享的字段进行的任何更新都需要正确同步。
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/