This week's giveaway is in the Android forum.
We're giving away four copies of Android Security Essentials Live Lessons and have Godfrey Nolan on-line!
See this thread for details.
The moose likes Threads and Synchronization and the fly likes My Producer/Consumer problem won't work. Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login


Win a copy of Android Security Essentials Live Lessons this week in the Android forum!
JavaRanch » Java Forums » Java » Threads and Synchronization
Bookmark "My Producer/Consumer problem won Watch "My Producer/Consumer problem won New topic
Author

My Producer/Consumer problem won't work.

azuki ooh
Greenhorn

Joined: Nov 07, 2008
Posts: 20
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!










    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
    >

    But mine is like this:

    ending...There are 0 missionaries left in the pot
    Cook has put 4 missionaries into pot.
    Cook has put 2 missionaries into pot.
    Cook has put 2 missionaries into pot.
    Cook has put 2 missionaries into pot.
    Cook has put 5 missionaries into pot.
    Cook has put 4 missionaries into pot.
    >

    Anayonkar Shivalkar
    Bartender

    Joined: Dec 08, 2010
    Posts: 1502
        
        5

    Hi azuki,

    Welcome to CodeRanch!

    Good to see that you are using code tags even in initial posts!

    Here at CodeRanch, we do not encourage to ask/provide for ready-made answers, but we strongly encourage to discuss the issues.

    Coming to your problem, I haven't gone through very much detail of requirement, but going by the code, I think the main problem is getServingFromPot method from Savage class. The comment says that but that code part is inside while loop.

    Now, you've handled the scenario where nuOfServings are zero (by the way, why are you using an array of length 1? why not a simple int?). But what if servings are available? Then the code will not enter in while loop, and I don't see any code handling this scenario (i.e. if the servings are already available, nothing will happen).

    I hope this helps.


    Regards,
    Anayonkar Shivalkar (SCJP, SCWCD, OCMJD, OCEEJBD)
    Manish Sridharan
    Ranch Hand

    Joined: Jul 19, 2005
    Posts: 64
    Hi Azuki,

    I can see there are couple of problems with the current code that you have posted.
    1. You need before in the Admin class.
    2. Cook class is defined as Thread but start() method is not invoked. Do you really need this class as Thread ?
    3. In my opinion, Timer class is not required. Function defined in the Timer class should be part of Savage and Cook Class . You just need to invoke in eat and cook function.

    Hope this helps.

    Cheers


    Manish S.
    azuki ooh
    Greenhorn

    Joined: Nov 07, 2008
    Posts: 20
    Thanks Anayonkar and Manish for your comments. 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. Yes, I am hoping to learn as much as I can from this forum. I am not expect ready answer as that will not help me to enhanced my skill. Yes, thanks for pointing out the missing join(). I need to wait for all the Threads to finish before printing the ending. 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.
    Steve Luke
    Bartender

    Joined: Jan 28, 2003
    Posts: 4167
        
      21

    In addition to the points made previously, your synchronization scheme, the wait()s and notifyAll()s don't work. Each of your instances of Savage synchronizes on itself, and wait()s on its own lock. The Cook instance synchronizes on itself and notifyAll()s on its lock. Since the Savage instances are wait()ing on a different lock they never get the notification from the Cook. You need to synchronize all the threads on the same Object's lock, and use that shared Object to do the wait() and notifyAll() from.

    For example, the cook should do:

    And the Savage should do:


    Steve
    Steve Luke
    Bartender

    Joined: Jan 28, 2003
    Posts: 4167
        
      21

    azuki ooh wrote: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.

    I think that is a most excellent design. The Pot would make a great point to synchronize on, and could keep track of the data which is shared between threads - the number of servings it currently has. So if the putServingsInPot() is supposed to be in Cook, then maybe split the action into two parts - 1 part in the Cook#putServingsInPot() method (the cook generates the number of servings to make, and takes the time to make the servings). And the second part in the Pot class which sets the number of available servings and notifies the Savages (maybe call it addServings(int servingsCount)).

    The Savages could also use the Pot when it is their time to getServingFromPot(). The part where they take time to eat, and notify the Cook it is his turn to cook would be done in the Savage class, and the part where they have to wait for available servings, and they decrement the number available is done in the Pot.

    But now that I look at getServingFromPot(): that method is not right at all. You will have to spend some time thinking about what it is supposed to to. It probably will lead to a change in the Cook as well (because the Cook will have to wait() until there is no more servings at some point).
    Steve Luke
    Bartender

    Joined: Jan 28, 2003
    Posts: 4167
        
      21

    Hi azuki,

    I split the post you made from the old topic about the main/child threads into its own topic, found here: http://www.coderanch.com/t/607584/threads/java/Main-method-finishes-threads-running.
     
    With a little knowledge, a cast iron skillet is non-stick and lasts a lifetime.
     
    subject: My Producer/Consumer problem won't work.
     
    Similar Threads
    Sieve of Eratosthenes
    The Savage Nation
    iterating with a scriptlet, can't get the values into js arr
    getter not running
    Problem With Algorithm Involving Recursion and String Manipulation