Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java线程中wait和notify方法的正确使用_Java_Multithreading_Concurrency - Fatal编程技术网

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(

我不熟悉Java多线程。我使用wait和notify创建了简单的生产者-消费者模式,但我的生产者在开始时只被调用一次

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();
            }
        }
    }
}