具有等待/通知功能的生产者消费者代码不适用于第二个生产者

时间:2018-12-17 22:15:09

标签: java multithreading queue producer-consumer notify

这是我上一个问here的问题的后续问题。

我现在正在使用PriorityBlockingQueue。我将制作人更改为以下内容:

synchronized(Manager.queue) {
    Manager.queue.add(new Job());
    Manager.queue.notify();
}

并将Consumer更改为以下内容。完整的代码框架在这里:

//my consumer thread run()
public void run() {
synchronized(Manager.queue) {
    while (Manager.queue.peek() == null) {
                System.out.println("111111111111111");
                try {
                    Manager.queue.wait();
                } catch (InterruptedException e) {
                }
            }
    Job job=Manager.queue.peek();
if (job != null) {
                submitJob(job);
                if (job.SubmissionFailed.equals("false")) {
                    // successful submission. Remove from queue. Add to another.
                    Manager.queue.poll();
                    Manager.submissionQueue.put(job.uniqueid, job);
}
}
}

我的代码仅在第一次(首次生产和首次使用)下起作用,但第二次则无效。我猜在某处等待/通知逻辑失败。生产者将新作业推送到队列中,但消费者不再peek个项目。实际上,它甚至都没有进入while循环并且不再进行111111111111111打印。

出什么问题了?如何解决?

1 个答案:

答案 0 :(得分:3)

您可以将所有这些代码简化为:

在生产者中:

Manager.queue.add(new Job());

以及在消费者中:

while (true) {
    try {
        submitJob(Manager.queue.take()); //or do something else with the Job
        //your code here, then remove the break
        break;
    } catch (InterruptedException ex) {
        //usually no need to do anything, simply live on unless you
        //caused that
    }
}
//or your code here, then you need an surrounding while and the break

使用PriorityBlockingQueue时,您不需要任何syncronized语句,因为它们已经在PriorityBlockingQueue内部。根据文档take(),如有必要,请等待添加元素,然后poll对其进行添加。请参阅https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/PriorityBlockingQueue.html#take()以供参考。

对于InterruptedException,您可能想在这里看看:Handling InterruptedException in Java

编辑:添加了丢失的try{} catch()