gpt4 book ai didi

java - 生产者-消费者在单个消费者和任意数量的生产者的情况下仅使用notify()

转载 作者:行者123 更新时间:2023-12-02 04:09:22 26 4
gpt4 key购买 nike

下面是我用于实现生产者-消费者问题的代码。使用 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){}
}
}

最佳答案

为了能够使用.notify(),您需要保证任何可能唤醒线程“消耗“通知的全部“原因”

例如,在您的情况下消费者(方法.get_item)释放缓冲区中单个元素的空间。这就是消费者通知的原因。因为您使用单一消费者模型,因此只有生产者(方法.add_item)可以因为此通知而被唤醒。 生产者 使用整个释放的元素将信息存储到其中。

因此,使用 .notify() 是消费者可以的

从另一方面来说,由于您使用多个生产者来自一个生产者的通知可能会唤醒另一个生产者。当然,一个生产者不会消耗另一生产者的效果。

因此,使用 .notify() 作为生产者是不好的

解决问题的最原始方法是使用不同的通知:一种用于消费者,一种用于生产者。因此,生产者中的通知只能唤醒消费者,消费者消费生产者存储的信息。可以使用 Condition 来实现同一关键部分下的不同通知:

public class Buffer
{
final Lock lock = new ReentrantLock();
final Condition notFull = lock.newCondition();
final Condition notEmpty = lock.newCondition();

// `volatile` isn't needed for objects accessed under critical section
private String content = "";
private boolean isEmpty = true;

// Use lock instead of `synchronized`.
public void addItem(String s)
{
lock.lock();
try {
while(!isEmpty){
try {
notFull.await(); // Analogue for wait()
} catch (InterruptedException e) {
e.printStackTrace();
}
};
content = s;
isEmpty = false;
notEmpty.signal(); // Analogue for notify()
} finally {
lock.unlock();
}
}

// Use lock instead of `synchronized`.
public String getItem()
{
lock.lock();
try {
while(isEmpty) {
try {
notEmpty.await(); // Analogue for wait()
} catch (InterruptedException e) {
e.printStackTrace();
}
};
String temp = content;
isEmpty = true;
notFull.signal(); // Analogue for notify()
return temp;
} finally {
lock.unlock();
}
}
}

关于java - 生产者-消费者在单个消费者和任意数量的生产者的情况下仅使用notify(),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33939539/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com