Page 1 of 2 12 Last
  • Jump to page:
    #1
  1. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Mar 2013
    Posts
    16
    Rep Power
    0

    Producer/Consumer problem.


    A tribe of savages eats communal dinners from a large pot that can hold M servings of stewed missionaries. When a savage wants to eat, he helps himself from the pot, unless it is empty. If the pot is empty, the savage wakes up the cook and then waits until the cook has refilled the pot.

    1. Admin class: This class creates the cook and generates arrival of 10 savages. The class also keeps track of the number of servings in the pot (using an array of size 1) and prints the number of servings left in the pot after all the savages have eaten.

    2. Cook class: This class models the cooking done by the cook.
    It should have a method putServingsInPot() that performs the following:
    • generate a random number M (between 1 and 5 inclusive)

    • show a message the cook has put M missionaries into the pot.

    • include a timing delay to represent the cooking relative to M.

    This method is invoked only when the pot is empty.

    3. Savage class: This class models the behaviour of the savages.
    It should have a suitable method that performs the following:
    • get a serving from the pot

    • include a timing delay to represent the time spent eating

    • deduct one serving from the pot

    • show messages that the savage starts eating and has finished eating

    When getting a serving from the pot, if the pot is empty, the cook’s method putServingsInPot() needs to be invoked.

    The output suppose to look something like this:


    [Post New]posted Yesterday 10:40:23 PM
    Quote Edit
    I am suppose to write a program to simulate this situation.

    A tribe of savages eats communal dinners from a large pot that can hold M servings of stewed missionaries. When a savage wants to eat, he helps himself from the pot, unless it is empty. If the pot is empty, the savage wakes up the cook and then waits until the cook has refilled the pot.

    Admin class: This class creates the cook and generates arrival of 10 savages. The class also keeps track of the number of servings in the pot (using an array of size 1) and prints the number of servings left in the pot after all the savages have eaten.

    Cook class: This class models the cooking done by the cook.
    It should have a method putServingsInPot() that performs the following:

    generate a random number M (between 1 and 5 inclusive)
    show a message the cook has put M missionaries into the pot.
    include a timing delay to represent the cooking relative to M.



    This method is invoked only when the pot is empty.

    Savage class: This class models the behaviour of the savages.
    It should have a suitable method that performs the following:
    get a serving from the pot

    include a timing delay to represent the time spent eating
    deduct one serving from the pot
    show messages that the savage starts eating and has finished eating



    When getting a serving from the pot, if the pot is empty, the cook’s method putServingsInPot() needs to be invoked.

    These are my codes but the output is totally wrong. But I just can't understand where goes wrong Please help!

    view plaincopy to clipboardprint?
    Note: Text content in the code blocks is automatically word-wrapped

    public class Admin
    {
    public static void main (String[] args)
    {
    int[] numOfServings = new int[1];
    Cook cook = new Cook(numOfServings);
    Savage[] savage = new Savage[10];



    for (int i = 0; i<savage.length; i++)
    {
    savage[i] = new Savage(i+1, numOfServings, cook);
    savage[i].start();

    }


    System.out.println("ending...There are " + numOfServings[0] + " missionaries left in the pot");
    }
    }



    view plaincopy to clipboardprint?
    Note: Text content in the code blocks is automatically word-wrapped

    public class Cook extends Thread
    {
    private int[] numOfServings;

    public Cook(int[] numOfServings)
    {
    this.numOfServings = numOfServings;
    }

    public void run()
    {

    putServingsInPot();

    }

    public synchronized void putServingsInPot()
    {
    int m = (int)(Math.random()*5)+1;
    Timer.cook(m);
    numOfServings[0]+=m;
    System.out.println("Cook has put " + m + " missionaries into pot.");
    notifyAll();
    }
    }



    view plaincopy to clipboardprint?
    Note: Text content in the code blocks is automatically word-wrapped

    public class Savage extends Thread
    {
    private int id;
    private int[] numOfServings;
    private Cook c;

    public Savage(int id, int[] numOfServings, Cook c)
    {
    this.id=id;
    this.numOfServings = numOfServings;
    this.c=c;
    }

    public void run()
    {
    for(int i=0; i><2; i++)
    {
    getServingFromPot();
    }
    }

    public synchronized void getServingFromPot()
    {
    while(numOfServings[0]==0)
    {
    c.putServingsInPot();

    try{
    wait();
    } catch (Exception e){}

    //out of while means cook has put missionaries into pot
    System.out.println("Salvage " + id + " getting a serving to eat");
    Timer.eat(id);
    numOfServings[0]--;
    System.out.println("Salvage " + id + " finished eating");

    }



    }
    }




    view plaincopy to clipboardprint?
    Note: Text content in the code blocks is automatically word-wrapped

    public class Timer
    {
    public static void eat(int time)
    {
    duration ((time+10)*2);
    }

    public static void cook (int share)
    {
    duration (share*100);
    }

    public static void duration(int time)
    {
    int speedFactor = 1000;
    for(int j = 0; j<time; j++)
    {
    for(int k = 0; k><speedFactor; k++)
    {
    double r = (k/2)*2;
    }
    }
    }
    }



    The output suppose to be like this:

    Cook has put 5 missionaries into pot
    Savage 0 getting a serving to eat
    Savage 3 getting a serving to eat
    Savage 5 getting a serving to eat
    Savage 1 getting a serving to eat
    Savage 9 getting a serving to eat
    There are no more missionaries in the pot!
    Cook has put 2 missionaries into pot
    Savage 5 finished eating
    Savage 3 finished eating
    Savage 0 finished eating
    Savage 1 finished eating
    Savage 9 finished eating
    Savage 7 getting a serving to eat
    Savage 8 getting a serving to eat
    There are no more missionaries in the pot!
    Cook has put 5 missionaries into pot
    Savage 8 finished eating
    Savage 7 finished eating
    Savage 6 getting a serving to eat
    Savage 4 getting a serving to eat
    Savage 2 getting a serving to eat
    Savage 4 finished eating
    Savage 6 finished eating
    Savage 2 finished eating
    There are 2 missionaries in the pot
    This is what I have and the output is totally wrong But I don't understand why.

    Code:
    public class Admin
    {
        public static void main (String[] args)
        {
            
            Cook cook = new Cook();
            Savage[] savage = new Savage[10];
            int[] numOfServings = new int[1];
            
                    
            for(int i = 0; i<savage.length; i++)
            {
                savage[i] = new Savage(numOfServings, i+1, cook);
                savage[i].start();
            }
            
            
            
            System.out.println("Ending...There are " + numOfServings[0] + " missionarie left in the pot");
        }
    }
    Code:
    public class Cook
    {
    
        public synchronized void putServingsInPot (int[] numOfServings)
        {
            int m = (int)(Math.random()*5)+1;
            Timer.cook(m);
            numOfServings[0]+=m;
            System.out.println("Cook has put " + m + " missionaries into pot.");
            notifyAll();
            
        }
        
    }
    Code:
    public class Savage extends Thread
    {
        private int[] numOfServings;
        private int id;
        private Cook c;
    
        public Savage(int[] numOfServings, int id, Cook c)
        {
            this.numOfServings=numOfServings;
            this.id=id;
            this.c=c;
        }
    
        public void run()
        {
            for(int i = 0; i<2; i++)
            {
                getServingsFromPot(id);
            }
        }
    
        public synchronized void getServingsFromPot(int id)
        {
            try{
                while(numOfServings[0]==0)
                {
                    System.out.println("There's no more missionary in the pot!");
                    c.putServingsInPot(numOfServings);
                    wait();
                }
            } catch(Exception e){}
    
            System.out.println("Savage " + id + " getting a serving to eat");
            Timer.eat(id);
            numOfServings[0]--;
            System.out.println("Savage " + id + " finished eating");
        }
    }
    Code:
    public class Timer
    {
        public static void cook(int n)
        {
          duration(n*100);  
        }
        
        public static void eat(int id)
        {
            duration(id*10+50);
        }
        
        
        public static void duration (int time)
        {
            int speedFactor = 1000000;
            for(int j = 0 ; j<time; j++)
            {
                for (int k = 0; k < speedFactor; k++)
                {
                    double r = k/2*2;
                }
            }
        }
    }
    This is my output which is completely wrong.
    There's no more missionary in the pot!
    There's no more missionary in the pot!
    There's no more missionary in the pot!
    There's no more missionary in the pot!
    There's no more missionary in the pot!
    There's no more missionary in the pot!
    There's no more missionary in the pot!
    There's no more missionary in the pot!
    There's no more missionary in the pot!
    There's no more missionary in the pot!
    Cook has put 4 missionaries into pot.
    Cook has put 5 missionaries into pot.
    Cook has put 3 missionaries into pot.
    Cook has put 1 missionaries into pot.
    Cook has put 3 missionaries into pot.
    Cook has put 5 missionaries into pot.
    Cook has put 3 missionaries into pot.
    Cook has put 1 missionaries into pot.
    Cook has put 1 missionaries into pot.
    Cook has put 5 missionaries into pot.
    When there's no more missionaries in pot, the Savage should call putServingsInPot() in the Cook class and it wait! But it's not working. why?
  2. #2
  3. Contributing User
    Devshed Expert (3500 - 3999 posts)

    Join Date
    Aug 2010
    Location
    Eastern Florida
    Posts
    3,711
    Rep Power
    347
    output which is completely wrong.
    Can you explain what the output should look like and post an example?

    The wait() and notifyAll() methods need to use the SAME object to use its monitor. Read the API doc for the Object class for those methods.
    Last edited by NormR; March 17th, 2013 at 03:34 PM.
  4. #3
  5. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Mar 2013
    Posts
    16
    Rep Power
    0
    Originally Posted by NormR
    Can you explain what the output should look like and post an example?

    The wait() and notifyAll() methods need to use the SAME object to use its monitor. Read the API doc for the Object class for those methods.
    I thought I have posted a sample correct output:

    Savage 0 getting a serving to eat
    Savage 3 getting a serving to eat
    Savage 5 getting a serving to eat
    Savage 1 getting a serving to eat
    Savage 9 getting a serving to eat
    There are no more missionaries in the pot!
    Cook has put 2 missionaries into pot
    Savage 5 finished eating
    Savage 3 finished eating
    Savage 0 finished eating
    Savage 1 finished eating
    Savage 9 finished eating
    Savage 7 getting a serving to eat
    Savage 8 getting a serving to eat
    There are no more missionaries in the pot!
    Cook has put 5 missionaries into pot
    Savage 8 finished eating
    Savage 7 finished eating
    Savage 6 getting a serving to eat
    Savage 4 getting a serving to eat
    Savage 2 getting a serving to eat
    Savage 4 finished eating
    Savage 6 finished eating
    Savage 2 finished eating
    There are 2 missionaries in the pot
  6. #4
  7. Contributing User
    Devshed Expert (3500 - 3999 posts)

    Join Date
    Aug 2010
    Location
    Eastern Florida
    Posts
    3,711
    Rep Power
    347
    How does the program start with "servings in the pot"?
  8. #5
  9. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Mar 2013
    Posts
    16
    Rep Power
    0
    Originally Posted by NormR
    How does the program start with "servings in the pot"?
    The program starts with creating the Savage and running them.

    I am using int[] instead of int for numOfServings because I need to pass as reference. If I use int I would be passing as value.

    I am also not sure if I need a Cook class. Looking at the question, it seems like only Savage run concurrently. Method in cook is only invoked when numOfServing = 0 and during this, Savage is at blocked state. So does this mean Cook can just be a normal class, no run() method needed.

    I was also thinking if I should create another class, say, Pot. And have getServingFromPot() and putServingToPot() in this class. But according to the question, putServingsInPot() is suppose to be in Cook class.
  10. #6
  11. Contributing User
    Devshed Expert (3500 - 3999 posts)

    Join Date
    Aug 2010
    Location
    Eastern Florida
    Posts
    3,711
    Rep Power
    347
    Did you see this part of my post:
    The wait() and notifyAll() methods need to use the SAME object to use its monitor. Read the API doc for the Object class for those methods.
  12. #7
  13. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Mar 2013
    Posts
    16
    Rep Power
    0
    Originally Posted by NormR
    Did you see this part of my post:
    The wait() and notifyAll() methods need to use the SAME object to use its monitor. Read the API doc for the Object class for those methods.
    Yes, I saw your part, wait() and notifyAll() need to use the same object. Does that mean I should create a class, say Pot? And put wait() and notifyAll() in this class? According to the question, putServingsInPot() is suppose to be in Cook class. Shouldn't my notifyAll() be in putServingsInPot()?
  14. #8
  15. Contributing User
    Devshed Expert (3500 - 3999 posts)

    Join Date
    Aug 2010
    Location
    Eastern Florida
    Posts
    3,711
    Rep Power
    347
    There are many ways for wait() and notify() to share an object. For example:
    Code:
    Object mon = new Object();   //  define an object to be the monitor
    ...
    mon.wait();
    ...
    mon.notify();
  16. #9
  17. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Mar 2013
    Posts
    16
    Rep Power
    0
    I was told now that the Cook is not a thread - it is a shared resource since any of the savages can wake up the cook. The cook also does not need to know how many servings are in the pot, since its responsibility is just to cook.

    Code:
    public class Cook
        {  
            public synchronized void putServingsInPot (int[] numOfServings)  
            {     
                int m = (int)(Math.random()*5)+1;  
                Timer.cook(m);  
                numOfServings[0]+=m;  
                System.out.println("Cook has put " + m   
                    + " missionaries into pot.");      
                notifyAll();      
                 
            }  
        }
    Code:
     public class Savage extends Thread  
        {  
            private int[] numOfServings;  
            private int id;  
            private Cook c;  
          
            public Savage(int[] numOfServings, int id, Cook c)  
            {  
                this.numOfServings=numOfServings;  
                this.id=id;  
                this.c=c;  
            }  
          
            public void run()  
            {  
                for(int i = 0; i<2; i++)  
                {  
                    getServingsFromPot();  
                }  
            }  
          
            public synchronized void getServingsFromPot()  
            {  
          
                while(numOfServings[0]==0)  
                {  
                    System.out.println("There's no more missionary in the pot!");  
                    c.putServingsInPot(numOfServings);  
          
                    try{  
                        wait();  
                    } catch (InterruptedException e){}  
                      
                      
                }  
                  
                  
                  
          
                System.out.println("Savage " + id + " getting a serving to eat");  
                Timer.eat(id);  
                numOfServings[0]--;  
                System.out.println("Savage " + id + " finished eating");  
          
            }  
        }
    Code:
    public class Admin  
        {  
            public static void main (String[] args)  
            {  
          
                Cook cook = new Cook();  
                Savage[] savage = new Savage[10];  
                int[] numOfServings = new int[1];  
          
                cook.putServingsInPot(numOfServings);        
                for(int i = 0; i<savage.length; i++)  
                {  
                    savage[i] = new Savage(numOfServings, i+1, cook);  
                    savage[i].start();  
          
                }  
          
                /*try{ 
                    for(int i = 0; i><savage.length; i++) 
                        savage[i].join(); 
                } catch (InterruptedException e){}*/  
          
                //System.out.println("Ending...There are " + numOfServings[0]   
                //    + " missionarie left in the pot");  
            }  
        }
    When I run this, the debugger tells me that my main thread finished and there are still some other threads waiting. I don't understand the flow of process. Can someone help me understand the flow of process here and why there are still threads waiting?
    Last edited by Azuki; March 18th, 2013 at 10:22 AM. Reason: spotted error
  18. #10
  19. Contributing User
    Devshed Expert (3500 - 3999 posts)

    Join Date
    Aug 2010
    Location
    Eastern Florida
    Posts
    3,711
    Rep Power
    347
    If the wait() method in a Savage class object is called, how will the thread that is queued on the monitor for that object ever be removed from the queue by a notify on that same Savage object?

    The notifyAll() method called in the Cook class object ONLY releases threads that are queued on the monitor for that Cook class object. Not connected to any of the threads queued on Savage objects when they called wait().
    Last edited by NormR; March 18th, 2013 at 10:28 AM.
  20. #11
  21. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Mar 2013
    Posts
    16
    Rep Power
    0
    Originally Posted by NormR
    If the wait() method in a Savage class object is called, how will the thread that is queued on the monitor for that object ever be removed from the queue by a notify on that same Savage object?

    The notifyAll() method called in the Cook class object ONLY releases threads that are queued on the monitor for that Cook class object. Not connected to any of the threads queued on Savage objects when they called wait().
    I removed the notifyAll() in the Cook class and add to the Savage class, but still same problem. Main thread finished with some thread still waiting. I don't quite see the flow of process.

    Code:
    public synchronized void getServingsFromPot()
        {
    
            while(numOfServings[0]==0)
            {
                System.out.println("There's no more missionary in the pot!");
                c.putServingsInPot(numOfServings);
    
                try{
                    wait();
                } catch (InterruptedException e){}
                
                
            }
            //out of while loop means cook has add to numOfServings, so notifyAll
            notifyAll(); 
            
            
            
    
            System.out.println("Savage " + id + " getting a serving to eat");
            Timer.eat(id);
            numOfServings[0]--;
            System.out.println("Savage " + id + " finished eating");
    
        }
  22. #12
  23. Contributing User
    Devshed Expert (3500 - 3999 posts)

    Join Date
    Aug 2010
    Location
    Eastern Florida
    Posts
    3,711
    Rep Power
    347
    Having the notify in method following wait doesn't make sense. They only operate on their own object. The other Savage objects won't be effected.

    The cook was the logical place to do the notify after adding items to the pot.

    You need to find ONE object that ALL the threads can use for their wait and notify calls.


    The print outs could use more info. All savage messages should have the savage id
    and many of the messages should show the current value of numOfServings[0]
  24. #13
  25. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Mar 2013
    Posts
    16
    Rep Power
    0
    Why does my method getAServing() gets interrupted even though I already have synchronized keyword?

    Code:
    public class Cook  
    {  
        public int putServingsInPot()  
        {  
            int m = (int)(Math.random()*5)+1;  
            try  
            {  
                Thread.sleep(m*500);  
            } catch (InterruptedException e){}  
            System.out.println("Cook has put " + m + " missionaries into pot");  
            return m;  
        }  
    }
    Code:
     public class Savage extends Thread  
        {  
            int id;  
            int[]numOfServings;  
            Cook c;  
          
            public Savage(int id, int[] numOfServings, Cook c)  
            {  
                this.id=id;  
                this.numOfServings=numOfServings;  
                this.c=c;  
            }  
          
            public synchronized void getAServing()  
            {  
                if (numOfServings[0]==0)  
                {  
                    System.out.println("There are no more missionaries in the pot!");  
                    numOfServings[0]+=c.putServingsInPot();  
                }  
                  
                System.out.println("\t there are " + numOfServings[0] + " in pot now.");  
                System.out.println("Savage " + id + " getting a serving to eat.");  
                numOfServings[0]--;  
                  
            }  
              
            public void run()  
            {  
                getAServing();  
                try  
                {  
                    Thread.sleep((int)(Math.random()*100)+100);  
                } catch (InterruptedException e){}  
                System.out.println("Savage " + id + " finished eating.");  
            }  
          
        }
    Code:
    public class Admin  
    {  
        public static void main(String[] args)  
        {  
            Cook cook = new Cook();  
            Savage[] savage = new Savage[10];  
            int[] numOfServings = new int[1];  
      
            numOfServings[0] = cook.putServingsInPot();  
      
            for(int i = 0; i<savage.length; i++)  
            {  
                savage[i] = new Savage(i+1, numOfServings, cook);  
                savage[i].start();  
            }  
              
            for(int i = 0; i><savage.length; i++)  
            {  
                try{  
                    savage[i].join();  
                } catch(InterruptedException e){}  
            }  
      
            System.out.println("There are " + numOfServings[0] + " missionaries left in the pot.");  
        }  
    }

    My output
    Cook has put 1 missionaries into pot
    there are 1 in pot now.
    Savage 3 getting a serving to eat.
    There are no more missionaries in the pot!
    There are no more missionaries in the pot!
    There are no more missionaries in the pot!
    There are no more missionaries in the pot!
    There are no more missionaries in the pot!
    There are no more missionaries in the pot!
    There are no more missionaries in the pot!
    There are no more missionaries in the pot!
    There are no more missionaries in the pot!
    Savage 3 finished eating.
    Cook has put 1 missionaries into pot
    there are 1 in pot now.
    Savage 1 getting a serving to eat.
    Cook has put 1 missionaries into pot
    there are 1 in pot now.
    Savage 7 getting a serving to eat.
    Cook has put 1 missionaries into pot
    there are 1 in pot now.
    Savage 9 getting a serving to eat.
    Cook has put 1 missionaries into pot
    there are 1 in pot now.
    Savage 5 getting a serving to eat.
    Savage 7 finished eating.
    Savage 9 finished eating.
    Savage 1 finished eating.
    Savage 5 finished eating.
    Cook has put 2 missionaries into pot
    there are 2 in pot now.
    Savage 2 getting a serving to eat.
    Savage 2 finished eating.
    Cook has put 3 missionaries into pot
    there are 3 in pot now.
    Savage 4 getting a serving to eat.
    Savage 4 finished eating.
    Cook has put 4 missionaries into pot
    there are 4 in pot now.
    Savage 10 getting a serving to eat.
    Savage 10 finished eating.
    Cook has put 5 missionaries into pot
    there are 5 in pot now.
    Savage 8 getting a serving to eat.
    Cook has put 5 missionaries into pot
    there are 5 in pot now.
    Savage 6 getting a serving to eat.
    Savage 8 finished eating.
    Savage 6 finished eating.
    There are 4 missionaries left in the pot.
    The correct output should look something like this:

    Cook has put 5 missionaries into pot
    Savage 0 getting a serving to eat
    Savage 3 getting a serving to eat
    Savage 5 getting a serving to eat
    Savage 1 getting a serving to eat
    Savage 9 getting a serving to eat
    There are no more missionaries in the pot!
    Cook has put 2 missionaries into pot
    Savage 5 finished eating
    Savage 3 finished eating
    Savage 0 finished eating
    Savage 1 finished eating
    Savage 9 finished eating
    Savage 7 getting a serving to eat
    Savage 8 getting a serving to eat
    There are no more missionaries in the pot!
    Cook has put 5 missionaries into pot
    Savage 8 finished eating
    Savage 7 finished eating
    Savage 6 getting a serving to eat
    Savage 4 getting a serving to eat
    Savage 2 getting a serving to eat
    Savage 4 finished eating
    Savage 6 finished eating
    Savage 2 finished eating
    There are 2 missionaries left in the pot
  26. #14
  27. Contributing User
    Devshed Expert (3500 - 3999 posts)

    Join Date
    Aug 2010
    Location
    Eastern Florida
    Posts
    3,711
    Rep Power
    347
    Why does my method getAServing() gets interrupted even though I already have synchronized keyword?
    Can you explain where that happens? How is it shown in the print out?
  28. #15
  29. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Mar 2013
    Posts
    16
    Rep Power
    0
    Originally Posted by NormR
    Can you explain where that happens? How is it shown in the print out?
    See the repeated "There are no more missionaries in the pot!"
    I thought if should go on to the next line which is to call the cook method putServingsInPot(). But if doesn't.
Page 1 of 2 12 Last
  • Jump to page:

IMN logo majestic logo threadwatch logo seochat tools logo