Unexpected result return when implementing wait and notify

Viewed 101

I've made a wait and notify example program that is abstraction of a cake shop. there is a thread with role cake machine for producing cake and a thread with role waiter for delivering cake. My expectation is each time the CakeMachine class completes producing a cake it will send a notify to the Waiter class for delivering. When I run a program which produce 3 cake, the result shows that only one cake is delivered. Here is my code:

The Cake class for creating cake object:

class Cake {
private int weight;
private String color;

public Cake(int weight, String color) {
    this.weight = weight;
    this.color = color;
    }

public String toString(){
    return "The cake is in " + color  +" and is " + weight + " gram ";

    }
}

The CakeMachine class for producing cake:

class CakeMachine implements Runnable{


private List<Cake> listCake;

CakeMachine(List<Cake> listCake) {
    this.listCake = listCake;
}

public void  makeCake() {
        int weight = new Random().nextInt(20);
        Cake cake = new Cake(weight, "color code is  " + weight );
        listCake.add(cake);
        System.out.println("cake has been cooked ");
        listCake.notify();
}

@Override
public void run() {

        for (int i = 0; i < 3; i++) {
           synchronized (listCake) {
               makeCake();
           }
        }
    }
}

The Waiter class for delivering cake:

class Waiter implements Runnable {

private List<Cake> listCake;

Waiter(List<Cake> listCake) {
    this.listCake = listCake;
}

public void delivery() {
        System.out.println("Waiter is waiting for the cake ");

            try {
                listCake.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
         Cake cake = listCake.get(listCake.size() - 1);
         System.out.println(cake.toString() + "has been delivered to customers ");
}

@Override
public void run() {

    for (int i = 0; i < 3; i++)
    {
        synchronized (listCake) {
            delivery();
        }
    }
  }
}

And the main class:

public class WaitAndNotify {

    public static List<Cake> listCake = new ArrayList<>();

    public static void main(String[] args) {

    Thread waiter = new Thread(new Waiter(listCake));
    Thread cakeMachine = new Thread(new CakeMachine(listCake));
    waiter.start();
    cakeMachine.start();

    }
}

The result when run the program is:

Waiter is waiting for the cake 
cake has been cooked 
cake has been cooked 
cake has been cooked 
The cake is in color code is  18 and is 18 gram has been delivered to   customers 
Waiter is waiting for the cake 

Please help me to understand this situation.

2 Answers
Related