简体   繁体   English

Java线程中wait和notify方法的正确使用

[英]Proper use of wait and notify methods in Java threading

I am new to Java multithreading.我是 Java 多线程的新手。 I created simple producer-consumer pattern using wait and notify but my producer is getting called only once in tbe starting.我使用 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");
            }
        }
    }
}

I am creating separate threads for producer and consumer.我正在为生产者和消费者创建单独的线程。 Producer thread only gets called in the starting and then after it is never getting executed.生产者线程仅在开始时被调用,然后永远不会被执行。

I tried two option to overcome this issue.我尝试了两种选择来克服这个问题。 first I put while condition outside of synchronized block second is given below.首先我把 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();
            }
        }
    }
} 

Both works great.两者都很好用。 Which one the of the appropriate solution to use ?使用哪一种合适的解决方案? I am still unable to figure out why the code I put in question is not working properly.我仍然无法弄清楚为什么我提出的代码不能正常工作。

I am still unable to figure out why the code I put in question is not working properly我仍然无法弄清楚为什么我提出的代码不能正常工作

The wait() in producer() releases the monitor which allows consumer() to enter its synchronized block. producer()wait()释放允许consumer()进入其synchronized块的监视器。 Then the wait() in producer() starts waiting till consumer() calls notify() and releases the monitor (ie exits its synchronized block).然后producer()wait()开始等待,直到consumer()调用notify()释放监视器(即退出其synchronized块)。 You never exit synchronized in consumer() therefore the wait() in producer() is blocked forever你永远不会在consumer()退出synchronized ,因此producer()wait()被永远阻塞

I am still unable to figure out why the code I put in question is not working properly我仍然无法弄清楚为什么我提出的代码不能正常工作

I've managed to fix your code, and I've attached below the fixed code snippet.我已设法修复您的代码,并附在固定代码片段下方。

I've introduced a boolean instance variable named isConsumed for the ProducerConsumerWorld.我为 ProducerConsumerWorld 引入了一个名为 isConsumed 的布尔实例变量。 In doing so, what essentially happens is that after Producer Thread produces, he updates the state of isConsumed to false, since he has produced something which is yet to be consumed.在这样做时,本质上发生的是在 Producer Thread 产生之后,他将 isConsumed 的状态更新为 false,因为他已经产生了一些尚未被消费的东西。 Afterwards, the producer notifies the the Consumer thread, that Producer has finished producing.之后,生产者通知消费者线程,生产者已经完成生产。 Next, it invokes wait() on the ProducerConsumerWorld which releases Producer's lock on ProducerConsumerWorld.接下来,它调用 ProducerConsumerWorld 上的 wait() 来释放 Producer 对 ProducerConsumerWorld 的锁定。 Then, it waits for the lock on ProducerConsumerWorld.然后,它等待 ProducerConsumerWorld 上的锁定。

Meanwhile, the Consumer Thead acquires the lock on ProducerConsumerWorld, which allows it to enter the consumer method, where it checks if there is produce yet to be consumed.同时,Consumer Thead 获得了 ProducerConsumerWorld 的锁,这允许它进入消费者方法,在那里它检查是否有尚未消费的产品。 If so, it consumes and updates the isConsumed variable to true, and notifies the produce has been consumed.如果是这样,它会消耗并将 isConsumed 变量更新为 true,并通知产品已被消耗。 Then the consumer proceeds to releases its lock on ProducerConsumerWorld by calling wait(), and waits to reacquire the lock on ProducerConsumerWorld after Producer has consumed.然后消费者通过调用wait()继续释放其在ProducerConsumerWorld上的锁,并在Producer消费后等待重新获取ProducerConsumerWorld上的锁。

Note:笔记:

Calling notify() doesn't release a lock until the thread moves out of the synchronized block, or wait() is called, thus releasing the lock.调用notify() 不会释放锁,直到线程移出同步块,或者调用wait(),从而释放锁。

Source: Oracle's OCA/OCP Java SE 7 Study Guide Page 760来源:Oracle 的 OCA/OCP Java SE 7 学习指南第 760 页

Code:代码:

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

This gives me an output like,这给了我一个输出,

在此处输入图片说明

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM