Java线程中wait和notify方法的正确使用
我不熟悉Java多线程。我使用wait和notify创建了简单的生产者-消费者模式,但我的生产者在开始时只被调用一次Java线程中wait和notify方法的正确使用,java,multithreading,concurrency,Java,Multithreading,Concurrency,我不熟悉Java多线程。我使用wait和notify创建了简单的生产者-消费者模式,但我的生产者在开始时只被调用一次 public class ThreadApp { public static void main(String[] args) throws InterruptedException { ProducerConsumerWorldp = new ProducerConsumerWorld(); Thread t1 = new Thread(
public class ThreadApp {
public static void main(String[] args) throws InterruptedException {
ProducerConsumerWorldp = new ProducerConsumerWorld();
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
try {
p.producer();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
try {
p.consumer();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
t1.start();
t2.start();
t1.join();
t2.join();
}
}
class ProducerConsumerWorld{
public void producer() throws InterruptedException{
synchronized (this) {
while(true){
System.out.println("Producer thread started running");
wait();
System.out.println("Resumed Producing");
}
}
}
public void consumer() throws InterruptedException{
synchronized (this) {
while(true){
Thread.sleep(2000);
System.out.println("Consumer thread started running");
System.out.println("Press enter to consume all and start producing");
Scanner s = new Scanner(System.in);
s.nextLine();
notify();
Thread.sleep(2000);
System.out.println("consumed all");
}
}
}
}
我正在为生产者和消费者创建单独的线程。生产者线程只在开始时被调用,然后在它永远不会被执行之后才被调用
我尝试了两种方法来解决这个问题。首先,我把while条件放在同步块之外,下面给出了第二个条件
class ProducerConsumerWorld{
public void producer() throws InterruptedException{
synchronized (this) {
while(true){
System.out.println("Producer thread started running");
notify();
wait();
System.out.println("Resumed Producing");
}
}
}
public void consumer() throws InterruptedException{
synchronized (this) {
while(true){
Thread.sleep(2000);
System.out.println("Consumer thread started running");
System.out.println("Press enter to consume all and start producing");
Scanner s = new Scanner(System.in);
s.nextLine();
notify();
Thread.sleep(2000);
System.out.println("consumed all");
wait();
}
}
}
}
两者都很有效。使用哪一种合适的解决方案?我仍然无法理解为什么我提出的代码不能正常工作
我仍然无法理解为什么我提出的代码不能正常工作
producer()
中的wait()
释放监视器,允许consumer()
进入其synchronized
块。然后producer()
中的wait()
开始等待,直到consumer()
调用notify()
并释放监视器(即退出其synchronized
块)。您永远不会退出consumer()
中的synchronized
,因此producer()中的wait()
将永远被阻止
我仍然无法理解为什么我提出的代码不是
正常工作
我已经设法修复了您的代码,并在下面附加了修复的代码片段
我为ProducerConsumerWorld引入了一个名为isConsumed的布尔实例变量。在这样做的过程中,本质上发生的是,在生产者线程生成之后,他将isConsumed的状态更新为false,因为他已经生成了一些尚未被消费的东西。之后,生产者通知消费者线程,生产者已经完成了生产。接下来,它调用ProducerConsumerWorld上的wait(),释放ProducerConsumerWorld上的生产者锁。然后,它等待ProducerConsumerWorld上的锁
同时,消费者Thead获得ProducerConsumerWorld上的锁,这允许它进入Consumer方法,在该方法中检查是否有尚未消费的产品。如果是这样,它将使用isConsumed变量并将其更新为true,并通知产品已使用。然后消费者通过调用wait()释放其对ProducerConsumerWorld的锁定,并在生产者消费后等待重新获取对ProducerConsumerWorld的锁定
注:
调用notify()不会释放锁,直到线程移出同步块,或者调用wait(),从而释放锁
来源:Oracle的OCA/OCP Java SE 7研究指南第760页
代码:
这给了我一个输出,比如
并且没有看到消费者和生产者的独立线程-我可以看到两个方法…很明显,执行程序的main
class/方法在这里丢失了。@AKSW:我没有把主要方法的代码放在这里,因为我只是在那里为消费者和生产者创建了两个独立的线程。忘记wait()
和notify()
,它们是一种非常低级的机制。您最好学习JDK中的高级知识,例如使用BlockingQueue
管理您的生产者和消费者。@daniu感谢您的建议。我知道封锁队列。这是我想学习如何处理低水平的同步。为了更好地掌握多线程,为什么我的代码永远无法从cousumer中退出。我已经把notify()放在了最后一个see@HarshKanakhara我说过您永远不会退出consumer中的synchronized
块。您在consumer中的synchronized
中有一个无限循环。是的,您可以调用notify(),但您将永远呆在consumer中的synchronized
。因此,producer中的wait()无法返回。感谢此解决方案,但我不想使用任何第三个变量,因此没有必要使用wait和notify方法。我可以简单地使用同步块,并使我的变量可变以使其工作。这不是我的专业领域,但这看起来是一个很好的答案。然而,请不要在这里要求投票-我们认为这是“绒毛”,需要删除。如果你认为问题作者不知道投票,那么你可以在评论中提醒他们,但记住这是可选的。谢谢@halfer,我下次会注意的。请原谅我的新手:')
import java.util.Scanner;
public class ThreadApp {
public static void main(String[] args) throws InterruptedException {
ProducerConsumerWorld p = new ProducerConsumerWorld();
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
try {
p.producer();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
try {
p.consumer();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
t1.start();
t2.start();
}
}
class ProducerConsumerWorld{
boolean consumed = false;
public void producer() throws InterruptedException{
System.out.println("Producer thread started running");
synchronized (this) {
while(this.consumed == true){ // Consumer has consumed and is waiting for produce
System.out.println("Resumed Producing");
this.consumed = false;
notify();
wait();
}
}
}
public void consumer() throws InterruptedException{
synchronized (this) {
while(this.consumed == false){
Thread.sleep(2000);
System.out.println("Consumer thread started running");
System.out.println("Press enter to consume all and start producing");
Scanner s = new Scanner(System.in);
s.nextLine();
this.consumed = true;
System.out.println("consumed all");
notify();
wait();
}
}
}
}