3

I am trying to learn threads and hence I wrote a sample producer consumer problem wherein the producer produces numbers from 1 to 10 and the consumer has to display them. But only the consumer displays number 1 and stops.

As I said the program is not well written and might be absurd but still I want to figure out the reason why all the numbers from 1 to 10 are not printed as I will remembr best when I code rather than from examples.

I am using two varibales to track the completion of the Producres or consumers activity so that I can perform the other.

/getStatus(Consumer C) passing consumer reference so that producer gets a refrnce to consumer .. and it can be used to know status of consumer ..thats it ../

import java.lang.Math;
public class Hello{

public static void main(String args[]) {

    System.out.println("---1");
    new Consumer().start();

}

}

class Producer extends Thread{

public int produce = 0;
public Consumer consumerObj =null;
int count = 1;
boolean producerStatus = false;

public void run(){

    System.out.println("---4");
    synchronized(this){

        do{

            System.out.println("---6");
            produce = produce+1;
            producerStatus = true;
            notify();
            consumerObj.consumerStatus = false;
            System.out.println("---9");
            count = count+1;

        }while(count<=10 && consumerObj.getStatus());

    }

}

public int getItem(){
    return produce;
}



public boolean getStatus(Consumer c){
    consumerObj = c;
    return producerStatus;

}

}

class Consumer extends Thread{

boolean consumerStatus = false;
int count =0;
public void run(){

    System.out.println("---2");
    Producer p = new Producer();
    p.getStatus(this);
    p.start();
    try{
        System.out.println("---3");
        synchronized(p){
            System.out.println("---5");
            p.wait();

            System.out.println("---8");
        }
    }
    catch(Exception e){
            System.out.println("exception");
    }

    synchronized(p){
        try{
            while(p.getStatus(this) && count<=9 ){

                System.out.println("---7");
                int consume = p.getItem();
                System.out.println("the produced item is ----->"+consume);
                count = count+1;
                p.producerStatus  = false;
                consumerStatus = true;
                p.wait();                   
                System.out.println("---10");

            }
        }
        catch(Exception e){
            System.out.println("exception");
        }

    }

}

public boolean getStatus(){

    return consumerStatus;

}
}

Output :

---1
---2
---3
---5
---4
---6
---9
---8
---7
the produced item is ----->1
---10

After inputs from .. Suraj .. Now the program is working fine .. see below ..

import java.lang.Math; public class Hello{

public static void main(String args[]) {

    System.out.println("---1");
    new Consumer().start();

}

}

class Producer extends Thread{

public int produce = 0;
public Consumer consumerObj =null;
int count = 1;
boolean producerStatus = false;

public void run(){

    System.out.println("---4");

        do{
            if(consumerObj.getStatus()){


            System.out.println("---6");
            produce = produce+1;
            System.out.println("---9 -- >produce is -->"+produce);
            producerStatus = true;
            synchronized(this){

            notify();
            System.out.println("---6.111");
            }

            consumerObj.consumerStatus = false;
            count = count+1;


            }


        }while(count<=10);


}

public int getItem(){

    return produce;

}

public boolean getStatus(Consumer c){

    consumerObj = c;
    return producerStatus;

}

}



class Consumer extends Thread{

boolean consumerStatus = true;
int count =1;
public void run(){

    System.out.println("---2");
    Producer p = new Producer();
    p.getStatus(this);
    p.start();//can a thread1 wait on an thread2 before the thread2 hass tarted and in this case wll notify on the scnd thread reaally notify therad1 ..
    try{
        System.out.println("---3");
        synchronized(p){
            System.out.println("---5");
            p.wait();

            System.out.println("---8");
        }
    }
    catch(Exception e){
            System.out.println("exception");
    }


        try{
            while(count<=10 ){

                System.out.println("---7");
                int consume = p.getItem();
                System.out.println("the produced item is ----->"+consume);
                count = count+1;
                p.producerStatus  = false;
                consumerStatus = true;
                synchronized(p){
                p.wait();   
                System.out.println("---10");        
                }


            }
        }
        catch(Exception e){
            System.out.println("exception");
        }


}

public boolean getStatus(){

    return consumerStatus;

}

}
Mandar Pandit
  • 2,171
  • 5
  • 36
  • 58
crackerplace
  • 5,305
  • 8
  • 34
  • 42

3 Answers3

3

OK. The program is wrong.

  1. The consumer thread comes and waits for lock.
  2. The first iteration in the loop of producer will call notify but doesent release the lock as the while loop is inside synchronized block. It will iterarte 10 times without releasing the lock and ends up calling notify 10 times continuously.
  3. But the Consumer only gets to wakeup once and the second time the consumer calls wait() it keeps on waiting as there is noone to call notify now(as the Producer's all 10 iterations are over)

So the problem is Consumer thread is wating but there's no-one to notify it, as the Producer finished its all 10 iterations in 1 shot.

Suraj Chandran
  • 24,433
  • 12
  • 63
  • 94
  • Ur explanation is structured but I have few dbts .. You mean after each notfiy the producer shud give up the lock why so .. ?So to mak ethe code work shud I bring the while loop outside of the synchronized block. – crackerplace May 30 '11 at 14:40
  • the other doubt that I have is my producers execution depends on the status of the consumer ..as I set a flag in consumer based on which i execute .. thn without my consumers execution alternately how can producer execute continuosly .. – crackerplace May 30 '11 at 15:26
0

in Producer, you set

consumerObj.consumerStatus = false;

and check this value in loop condition immediately. Loops end after 1 cycle. After

count = count+1;

you should wait (for "consumption").

try{
    this.wait();
} catch (Exception e) {
    e.printStackTrace();
}

The same problem in Consumer. Last thing in the loop should be

p.wait();
bigGuy
  • 1,732
  • 1
  • 22
  • 37
  • i dont thnk that makes a diff when U have just one thread waitng on the othr .. stll tried it dint work .. – crackerplace May 30 '11 at 14:12
  • yep, sry. Wrote answer after quick look. Give me few minutes. – bigGuy May 30 '11 at 14:19
  • When u say this.wait() in producer you are waiting on the same thread how can this happen ? this refers to producer and calling this.wait() in same class ? – crackerplace May 30 '11 at 14:48
  • Because after i set the consumerStatus false in producer then the consumer shud change it to true after it executes so that now the producer can execute ...this is to ensure that repetitive producer executions dont happen .. stll its not working .. – crackerplace May 30 '11 at 14:50
0

You should use BlockingQueues. see http://www.javamex.com/tutorials/synchronization_producer_consumer_2.shtml.

The above implementation is ineffecient and it forces all consurmers to block. with multiple queues you can prevent all consumers from blocking. You can find examples on google. Java.util.concurrent Use it , it is there for a reason.