【发布时间】:2015-11-26 13:07:11
【问题描述】:
以下是我实现生产者-消费者问题的代码。使用notifyAll() 一切正常,但是由于性能原因,我想用notify() 替换所有出现的notifyAll()。
我发现通过将 notifyAll() 更改为 notify() 来替换这些调用会导致死锁发生。但是,替换这些调用的所有其他尝试都失败了。
是否有一些巧妙的方法可以用notify() 替换这些调用,从而使下面的代码适用于单个消费者和任意数量的生产者?
public class Buffer
{
private volatile String content = "";
private volatile boolean isEmpty = true;
public synchronized void addItem(String s)
{
while(!isEmpty){
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
};
content = s;
isEmpty = false;
notifyAll();
}
public synchronized String getItem()
{
while(isEmpty) {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
};
String temp = content;
isEmpty = true;
notifyAll();
return temp;
}
}
public class Producer implements Runnable
{
private String greeting;
private int repetitions;
private Buffer b;
public Producer(String aGreeting, int aRepetitions, Buffer aBuffer){
greeting = aGreeting;
repetitions = aRepetitions;
b = aBuffer;
}
public void run()
{
for(int i = 1; i <= repetitions; i++) {
b.addItem(greeting + i);
}
}
}
public class Consumer implements Runnable {
private String greeting;
private Buffer b;
public Consumer(String aGreeting, Buffer aBuffer){
greeting = aGreeting;
b = aBuffer;
}
public void run()
{
try
{
while(true){
System.out.println(greeting + b.getItem());
Thread.sleep(100);
}
}
catch(InterruptedException exception){}
}
}
【问题讨论】:
-
你可以在这里查看:github.com/pvllnspk/concurrency_problems/tree/master/src/cp,也许会发现一些有用的东西
-
你能用阻塞队列的概念代替你的实现吗? BlockingQueue 通过提供对 put() 和 take() 阻塞的开箱即用支持,惊人地简化了 Producer-Consumer 设计模式的实现。开发人员不需要编写令人困惑和关键的等待通知代码来实现通信。 BlockingQueue 是一个接口,Java 5 为它提供了不同的实现。
-
请检查这个,stackoverflow.com/questions/13774802/… 这个线程已经解释了一个很好的例子,说明为什么我们不应该使用 notify() 而不是 notifyAll()
-
您的代码会变得明显更加复杂(您需要为生产者和消费者提供单独的锁定对象),而好处很可能很小。我建议不要这样做。
标签: java concurrency java.util.concurrent