gpt4 book ai didi

java - wait()/notify() 无法正常工作

转载 作者:搜寻专家 更新时间:2023-11-01 03:33:50 26 4
gpt4 key购买 nike

我有一个 ConsumerProducer 对象,我想从两个不同的线程获取它的锁。类如下:

public class ConsumerProducer {

public String stringPool = null;

public void put(String s){
stringPool = s;
}

public String get(){
String ret = stringPool;
stringPool = null;
return ret;
}

}

线程实现类如下:

public class WaitNotifyTest implements Runnable {

private String threadType;
public ConsumerProducer cp;
public static volatile int i = 1;

public WaitNotifyTest(String threadType, ConsumerProducer cp) {
this.threadType = threadType;
this.cp = cp;
}

public static void main(String[] args) throws InterruptedException {

ConsumerProducer cp = new ConsumerProducer();
WaitNotifyTest test1 = new WaitNotifyTest("Consumer", cp);
WaitNotifyTest test2 = new WaitNotifyTest("Producer", cp);

Thread t1 = new Thread(test1);
Thread t2 = new Thread(test2);

t1.start();
t2.start();
t1.join();
t2.join();
}

@Override
public void run() {
while (true) {

if (threadType.equalsIgnoreCase("Consumer")) {
synchronized (cp) {
try {
if (null != cp.get()) {
cp.wait();
}
consume();
System.out.println("notify from Consumer");
cp.notify();
} catch (InterruptedException e) {
e.printStackTrace();
}
}

} else {
synchronized (cp) {
try {
if (null == cp.get()) {
cp.wait();
}
produce();
System.out.println("notify from Producer");
cp.notify();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
if (i == 5) {
break;
}
i++;
}
}

public void consume() {
System.out.println("Putting: Counter" + i);
cp.put("Counter" + i);
}

public void produce() {
System.out.println("getting: " + cp.get());
}

}

但是当我运行代码时,它遇到了某种死锁,并且像打印一样卡住了

Putting: Counter3
notify from Consumer

出现了严重错误,但我无法确定。请帮忙。

最佳答案

您的消费者正在做生产者的工作,而生产者正在做消费者的工作。交换他们的责任并修改条件等待。请引用下面的代码。

  1. Consumer会等到什么都拿不到的时候,他会释放cp的锁。这样生产者就有机会进入同步块(synchronized block)。
  2. 生产者只有在什么都没有的时候才生产,否则他会等待。之后,他就会释放cp的锁。这样消费者就有机会进入同步块(synchronized block)。
  3. 消费者是拿走东西的人。
  4. 制作人是把事情摆在桌面上的人。
  5. 根据您的评论。你想把计数器从 1 到 5,所以你应该只在生产者线程中添加 i++。您如何控制它在两个线程中的增加?
  6. cp对象调用get()不判断是消费者还是生产者,而是将null赋值给stringPool .这显然是错误的,并且会使消费者从公共(public)空间中获得空值。我添加了一个新方法 clearString(),它只会在消费者消费产品时将公共(public)空间设置为 null。

    public class WaitNotifyTest implements Runnable {

    private String threadType;
    public ConsumerProducer cp;
    public static volatile int i = 0;

    public WaitNotifyTest(String threadType, ConsumerProducer cp) {
    this.threadType = threadType;
    this.cp = cp;
    }

    public static void main(String[] args) throws InterruptedException {

    ConsumerProducer cp = new ConsumerProducer();
    WaitNotifyTest test1 = new WaitNotifyTest("Consumer", cp);
    WaitNotifyTest test2 = new WaitNotifyTest("Producer", cp);

    Thread t1 = new Thread(test1);
    Thread t2 = new Thread(test2);

    t1.start();
    t2.start();
    t1.join();
    t2.join();
    }

    @Override
    public void run() {
    while (true) {
    if (threadType.equalsIgnoreCase("Consumer")) {
    synchronized (cp) {
    try {
    /*
    * Consumer will wait when there is nothing to get and he will release the lock of cp.
    * So that producer has change to go into the synchronized block.
    */

    if (null == cp.get()) {
    cp.wait();
    }
    consume();
    System.out.println("notify from Consumer");
    cp.notify();
    } catch (InterruptedException e) {
    e.printStackTrace();
    }
    }

    } else {
    synchronized (cp) {
    try {
    /*
    * Producer only produce when there is nothing or he will wait. At the same time, he will release the lock of cp.
    * So that consumer has chance to go into the synchronized block.
    */
    if (null != cp.get()) {
    cp.wait();
    }
    i++;
    produce();
    System.out.println("notify from Producer");
    cp.notify();
    } catch (InterruptedException e) {
    e.printStackTrace();
    }
    }
    }
    if (i == 5) {
    break;
    }

    }
    }

    public void consume() {
    System.out.println("getting: " + cp.get());
    cp.clearString();
    }

    public void produce() {
    System.out.println("Putting: Counter" + i);
    cp.put("Counter" + i);
    }}

另请参阅 ConsumerProducer 类。

public class ConsumerProducer {
public String stringPool = null;

public void put(String s){
stringPool = s;
}

public String get(){
return stringPool;
}

public void clearString(){
stringPool = null;
}
}

关于java - wait()/notify() 无法正常工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38552173/

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