为什么在我的 java 代码中没有调用通知

why is notify not getting called in my java code

这是我的代码:

public class ProducerConsumer
{

    public static void main(String[] args)
    {
        ProduceCosumeData p = new ProduceCosumeData();
        ProducerT pt= new ProducerT(p); // with p obj i am creating thread
        ConsumerT ct=new ConsumerT(p); // with same p obj i am creating thread
        pt.start();
        ct.start();  //i am starting 2 threads
    }
}

class ProduceCosumeData
{
    boolean flag;
    public synchronized void printStringP(int n)
    {
        for(int i=0;i<n;i++)
        {
            try{
                if(flag)   //for frist time flag is flase so, wait will skip
                    wait();
                else
                    flag=true;    //for next time onwards wait() will get call

                System.out.print("Pay");
                notify();//after this why my wait() not canceling in inprintStringC()
            }catch(Exception e)
            {
                System.out.print(e);
            }
        }
    }
    public synchronized void printStringC(int n)
    {
        for(int i=0;i<n;i++)
        {
            try{
                wait();   // why it is not out of this after notify()
                System.out.print("Tm");
                notify();
            }catch(Exception e)
            {
                System.out.print(e);
            }
        }
    }
}

class ProducerT extends Thread
{
    ProduceCosumeData p;
    ProducerT(ProduceCosumeData p)
    { 
        this.p=p;   // i am saving the same obj for both threads
    }   
    public void run()
    {
        p.printStringP(10); //it will print 10 times pay
    }
}

class ConsumerT extends Thread
{
    ProduceCosumeData p;
    ConsumerT(ProduceCosumeData p)
    { 
        this.p=p;   // i am saving the same obj for both threads
    }
    public void run()
    {
        p.printStringC(10);   //it will print 10 times tm
    }
}

我期待以下输出:

PayTm
PayTm
PayTm
... 10 times

但我得到的输出是这样的:

Pay..

接下来是漫长的等待。

以上两个函数在同一个对象中。
为什么通知不释放 wait() 函数?即使我使用 notifyAll(),输出也保持不变。

printStringP 的第二次迭代中,属性 flagtrue,然后两个线程正在等待。

您在方法中使用了一般wait()同步。尝试使用对象同步版本,例如 synchronized(this){ wait(); } 然后无论如何,以防止多个线程对同一对象的循环依赖,这对任何多线程程序来说都是非常非常危险的。

或者,更简单地说,在您的 ProducerConsumerData class 中实现一个适当的 clone() 方法,然后将此对象传递给第一个线程,然后将其克隆传递给下一个线程。尝试在第二个线程的构造函数中使用 p.clone() 而不是 p

正如上面的回答,您可以让 printStringP() 的 notify() 只在标志为真时被调用,而不是总是被调用。

这是 classic 的误解,几乎所有尝试使用 waitnotify 的人都会犯错。真的,他们太老太破了,恕我直言,他们甚至不应该再被教了。

printStringP调用notify()printStringC还没有等待

class ProduceCosumeData {
    // Variable shared between threads should be volatile.
    volatile boolean flag;

    public synchronized void printStringP(int n) {
        for (int i = 0; i < n; i++) {
            try {
                //for frist time flag is flase so, wait will skip
                if (flag) {
                    System.err.println("Waiting in printStringP");
                    wait();
                } else {
                    System.err.println("flag now true");
                    flag = true;    //for next time onwards wait() will get call
                }
                System.out.print("Pay");
                System.err.println("printStringP notify");
                notify();//after this why my wait() not canceling in inprintStringC()
            } catch (Exception e) {
                System.out.print(e);
            }
        }
    }

    public synchronized void printStringC(int n) {
        for (int i = 0; i < n; i++) {
            try {
                System.err.println("Waiting in printStringC");
                wait();   // why it is not out of this after notify()
                System.out.print("Tm");
                System.err.println("printStringC notify");
                notify();
            } catch (Exception e) {
                System.out.print(e);
            }
        }
    }
}

class ProducerT extends Thread {

    ProduceCosumeData p;

    ProducerT(ProduceCosumeData p) {
        this.p = p;   // i am saving the same obj for both threads
    }

    public void run() {
        p.printStringP(10); //it will print 10 times pay
    }
}

class ConsumerT extends Thread {

    ProduceCosumeData p;

    ConsumerT(ProduceCosumeData p) {
        this.p = p;   // i am saving the same obj for both threads
    }

    public void run() {
        p.printStringC(10);   //it will print 10 times tm
    }
}

public void test() {
    ProduceCosumeData p = new ProduceCosumeData();
    ProducerT pt = new ProducerT(p); // with p obj i am creating thread
    ConsumerT ct = new ConsumerT(p); // with same p obj i am creating thread
    pt.start();
    ct.start();  //i am starting 2 threads
}

打印

flag now true
PayprintStringP notify
Waiting in printStringP
Waiting in printStringC

要解决这个问题 不要使用 wait/notify 除了非常有经验的人之外,它对所有人来说都是坏的。使用 Locks 和 Conditions 或几乎任何其他 java.util.concurrent class.

可以以稳定的方式实现相同的功能
Please find the below code snippet.

package com.java.examples;

public class ProducerConsumer {
    public static void main(String[] args) throws InterruptedException {
        ProduceCosumeData p = new ProduceCosumeData();
        ProducerT pt = new ProducerT(p); // with p obj i am creating thread
        ConsumerT ct = new ConsumerT(p); // with same p obj i am creating thread
        pt.start();
        Thread.sleep(1000);
        ct.start(); // i am starting 2 threads
    }
}

class ProduceCosumeData {
    boolean flag = false;

    public synchronized void printStringP(int n) {
        for (int i = 0; i < n; i++) {
            try {
                if (flag) {
                    notify();
                } else
                    flag = true;
                System.out.println("Pay");
                if (i <= n - 1) {
                    wait();
                } else {
                    break;
                }

            } catch (Exception e) {
                System.out.print(e);
            }
        }
        notify();
    }

    public synchronized void printStringC(int n) {
        for (int i = 0; i < n; i++) {
            try {
                if (flag) {
                    System.out.println("Tm");
                    if (i <= n - 1) {
                        notify();
                    } else {
                        break;
                    }
                } else
                    flag = false;
                wait();
            } catch (Exception e) {
                System.out.print(e);
            }
        }
    }
}

class ProducerT extends Thread {
    ProduceCosumeData p;

    ProducerT(ProduceCosumeData p) {
        this.p = p; // i am saving the same obj for both threads
    }

    public void run() {
        p.printStringP(10); // it will print 10 times pay
    }
}

class ConsumerT extends Thread {
    ProduceCosumeData p;

    ConsumerT(ProduceCosumeData p) {
        this.p = p; // i am saving the same obj for both threads
    }

    public void run() {
        p.printStringC(10); // it will print 10 times tm
    }
}

在您的代码中,您的一个线程正在调用通知,而另一个线程仍未等待。这会导致两个线程都在等待的死锁。

您需要修复同步标志的使用,如果不需要,请不要调用 wait。此外,在 wait() 之后检查锁定条件是否仍然可用是一个好习惯。

这是你的 ProduceConsumeData class,使用固定标志:

class ProduceCosumeData
{
    boolean flag;
    public synchronized void printStringP(int n)
    {
        for(int i=0;i<n;i++)
        {
            try{
                while (flag == true) {   
                    wait();
                }
                flag=true;
                System.out.print("Pay");
                notify();
            }catch(Exception e)
            {
                System.out.print(e);
            }
        }
    }
    public synchronized void printStringC(int n)
    {
        for(int i=0;i<n;i++)
        {
            try{
                while(flag == false) {
                    wait();
                }
                System.out.print("Tm");
                flag = false;
                notify();
            }catch(Exception e)
            {
                System.out.print(e);
            }
        }
    }
}