为什么通知不会在我的java代码中被调用

时间:2015-02-27 09:14:34

标签: java multithreading inter-process-communicat

这是我的代码:

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次

但是我得到的输出是:

  

支付..

接下来是漫长的等待。

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

5 个答案:

答案 0 :(得分:1)

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

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

这是您使用固定标志的ProduceConsumeData课程:

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

答案 1 :(得分:-1)

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

答案 2 :(得分:-1)

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

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

如上所述,你可以使printStringP()的notify()仅在flag为true时被调用,而不是总是。

答案 3 :(得分:-1)

这是一种典型的误解,几乎每个试图使用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

要解决此问题请勿使用等待/通知,除非经验丰富,否则它会被破坏。使用LockCondition或几乎任何其他java.util.concurrent类,可以以稳定的方式实现相同的功能。

答案 4 :(得分:-2)

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
    }
}